Scala предоставляет @varargs
аннотацию, которая генерирует метод пересылки Java varargs, что позволяет написать что-то вроде этого:
import scala.annotation.varargs
class Foo {
@varargs def foo(args: String*): Unit = {
args.foreach(println)
}
}
И затем, чтобы вызвать этот метод из Java, не создавая scala.Seq
:
Foo foo = new Foo();
foo.foo("a", "b");
Что довольно приятно.
К сожалению, часть пересылки, похоже, не возникает, когда метод является абстрактным:
trait Bar {
@varargs def bar(args: String*): Unit
}
class Baz extends Bar {
def bar(args: String*): Unit = {
args.foreach(println)
}
}
Теперь, если у нас есть этот код Java:
Bar bar = new Baz();
bar.bar("a", "b");
Мы получаем это исключение (во время выполнения):
java.lang.AbstractMethodError: Baz.bar([Ljava/lang/String;)V
Мы можем подтвердить проблему с помощью 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();
}
Таким образом, форвардер определенно не реализуется.
Помещение аннотаций к методам bar
не удается скомпилировать:
A method with a varargs annotation produces a forwarder method with the same
signature (args: Array[String])Unit as an existing method.
И, конечно, размещение аннотации только на bar
в Baz
означает, что мы не можем использовать пересылку из экземпляра bar
.
Кажется, что это ошибка, но это также кажется чрезвычайно простым в использовании, и я не вижу ничего в трекер проблема. Правильно ли я использую @varargs
? Если это так, есть ли обходной путь, который заставит его делать то, что вы ожидаете здесь?