2014-11-21 20 views
13

Scala cung cấp một @varargs annotation mà tạo ra một phương pháp giao Java varargs, mà làm cho nó có thể viết một cái gì đó như thế này:Phương pháp trừu tượng và chú thích varargs

import scala.annotation.varargs 

class Foo { 
    @varargs def foo(args: String*): Unit = { 
    args.foreach(println) 
    } 
} 

Và sau đó gọi phương pháp này từ Java mà không cần phải tạo a scala.Seq:

Foo foo = new Foo(); 
foo.foo("a", "b"); 

Điều này khá hay.

Thật không may là phần chuyển tiếp dường như không xảy ra khi phương pháp này là trừu tượng:

trait Bar { 
    @varargs def bar(args: String*): Unit 
} 

class Baz extends Bar { 
    def bar(args: String*): Unit = { 
    args.foreach(println) 
    } 
} 

Bây giờ nếu chúng ta có mã này Java:

Bar bar = new Baz(); 
bar.bar("a", "b"); 

Chúng tôi nhận được ngoại lệ này (khi chạy) :

java.lang.AbstractMethodError: Baz.bar([Ljava/lang/String;)V 

Chúng tôi có thể xác nhận sự cố với javap:

public interface Bar { 
    public abstract void bar(java.lang.String...); 
    public abstract void bar(scala.collection.Seq<java.lang.String>); 
} 

public class Baz implements Bar { 
    public void bar(scala.collection.Seq<java.lang.String>); 
    public Baz(); 
} 

Vì vậy, không, nhà giao nhận chắc chắn không được triển khai.

Đưa chú thích trên cả hai phương pháp bar thất bại trong việc biên dịch:

A method with a varargs annotation produces a forwarder method with the same 
signature (args: Array[String])Unit as an existing method. 

Và dĩ nhiên đặt chú thích chỉ trên bar trong Baz nghĩa là chúng ta không thể sử dụng giao nhận từ một trường hợp Bar.

Điều này có vẻ như nó phải là một lỗi, nhưng nó cũng có vẻ rất dễ dàng để chạy vào, và tôi không thấy bất cứ điều gì trong bộ theo dõi vấn đề. Tôi có đang sử dụng @varargs chính xác không? Nếu vậy, liệu có một cách giải quyết nào đó có thể khiến nó làm những gì bạn mong đợi ở đây không?

+0

Rất tiếc. Dường như với tôi một lỗi khác.Nhờ có một giải pháp 'jugaad' khác cho khả năng tương thích. Gosh! còn bao nhiêu người nữa? – Jatin

+0

Có vẻ như một con bọ. Thử gửi một lỗi mới cho trình theo dõi vấn đề của họ. – Luminous

Trả lời

2

Tôi không biết Scala, nhưng trong Java varargs chỉ là một mảng.

Vì vậy, trong Java nó sẽ làm việc theo cách này, với một cảnh báo:

package tests.StackOverflow.q27052394; 

import java.util.Arrays; 

public class Runner { 

    public interface Bar { 
     public abstract void bar(java.lang.String ... ss); 
    } 

    public static class Baz implements Bar { 
     public void bar(java.lang.String[] array) { 
      System.out.println(Arrays.toString(array)); 
     } 
    } 

    public static void main(String[] args) { 

     Bar b = new Baz(); 

     b.bar("hello", "world"); 

    } 

} 

Có thể nếu bạn có thể đánh lừa Scala theo cùng một cách, bạn sẽ khắc phục tình trạng lỗi.

+0

Thêm một phương thức 'def bar (args: Array [String]): Unit = bar (args: _ *)' thành 'Baz' thực sự có vẻ hoạt động (mặc dù nó không phải là rất dễ chịu). –

1

Một cách để đạt được những gì bạn muốn là để xác định giao diện trong Java như sau

interface Bar { 
    public void bar(String... args); 
} 

và sau đó để xác định việc thực hiện bình thường trong Scala như sau

class Baz extends Bar { 
    def bar(args: String*): Unit = { 
    args.foreach(println) 
    } 
} 

Scala trình biên dịch sẽ nhận ra rằng nó cần tạo phương thức kiểu vargs và sẽ tạo cả hai varargs và triển khai Seq.

đầu ra javap là như bạn mong chờ

public class Baz implements Bar { 
    public void bar(scala.collection.Seq<java.lang.String>); 
    public void bar(java.lang.String[]); 
    public Baz(); 
} 

interface Bar { 
    public abstract void bar(java.lang.String...); 
} 
Các vấn đề liên quan