Я пишу API, который я хочу использовать как в Scala, так и в Java. У меня есть полиморфный метод, определенный в классе Scala, и у меня возникают проблемы с вызовом его из Java.
Согласно этой совместимости FAQ на scala-lang.org, использование класса Scala, использующего расширенные языковые функции, "может быть сложным" , но не говорит, что это невозможно . Поскольку то, как передовые функции Scala переводят на Java, не документировано, предлагается разобрать файл класса, чтобы поэкспериментировать с его работой.
Пример кода
class Polymorphic {
def polyMethod[T](implicit om: Manifest[T]) = {
println(om.erasure.getName)
om.erasure.newInstance
}
}
object Polymorphic {
def main(args: Array[String]) {
val objOfT = (new Polymorphic).polyMethod[String]
}
}
Это прекрасно работает в Scala, печать "java.lang.String
"
Я запустил javap -c
в результирующем файле класса и получил следующий список для polyMethod
:
public java.lang.Object polyMethod(scala.reflect.Manifest);
Code:
0: getstatic #20; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_1
4: invokeinterface #27, 1; //InterfaceMethod scala/reflect/ClassManifest.erasure:()Ljava/lang/Class;
9: invokevirtual #33; //Method java/lang/Class.getName:()Ljava/lang/String;
12: invokevirtual #37; //Method scala/Predef$.println:(Ljava/lang/Object;)V
15: aload_1
16: invokeinterface #27, 1; //InterfaceMethod scala/reflect/ClassManifest.erasure:()Ljava/lang/Class;
21: invokevirtual #41; //Method java/lang/Class.newInstance:()Ljava/lang/Object;
24: areturn
3 основных проблемы:
- Метод полиморфен в своем типе возврата
- Параметр
Manifest
неявный в Java
- На самом деле я не могу передать параметр типа.
Реальный код проекта, с которым я пытаюсь это сделать, находится здесь:
https://github.com/ConnorDoyle/EnMAS/blob/master/clientServerPrototype/src/org/enmas/pomdp/State.scala
Моей конечной целью является создание универсального, но безопасного типа словаря данных. Он прекрасно работает в Scala, но мне бы очень хотелось, чтобы этот метод вызывался также из Java API. Моя мотивация дизайна - не допускать отражения, явного приведения и нулевых проверок в клиентском коде.
Редактировать: 18 ноября 2011 В ответ на комментарий @kassens ниже
Изменение определения polyMethod
на следующее:
def polyMethod[T](implicit om: Manifest[T]): T = {
println(om.erasure.getName)
om.erasure.newInstance.asInstanceOf[T]
}
дает точно такой же байт-код, когда я проверяю файл класса с помощью javap
.