nehme ich dieses Scala Merkmal haben:Java Interoperabilität Elende mit Scala Generika und Boxen
trait UnitThingy {
def x(): Unit
}
eine Implementierung Java Providing ist einfach genug:
import scala.runtime.BoxedUnit;
public class JUnitThingy implements UnitThingy {
public void x() {
return;
}
}
Nun wollen wir mit einem allgemeinen Merkmal beginnen:
trait Foo[A] {
def x(): A
}
trait Bar extends Foo[Unit]
der Ansatz oben wird nicht funktionieren, da die Einheit x
n zurückgibt ow geboxt, aber die Abhilfe ist einfach genug:
import scala.runtime.BoxedUnit;
public class JBar implements Bar {
public BoxedUnit x() {
return BoxedUnit.UNIT;
}
}
Nehmen wir nun an habe ich eine Implementierung mit x
auf der Scala Seite definiert bekam:
trait Baz extends Foo[Unit] {
def x(): Unit =()
}
Ich weiß, dass ich das nicht x
aus sehen Java, so definiere ich meine eigene:
import scala.runtime.BoxedUnit;
public class JBaz implements Baz {
public BoxedUnit x() {
return BoxedUnit.UNIT;
}
}
Aber das sprengt:
[error] .../JBaz.java:3: error: JBaz is not abstract and does not override abstract method x() in Baz
[error] public class JBaz implements Baz {
[error] ^
[error] /home/travis/tmp/so/js/newsutff/JBaz.java:4: error: x() in JBaz cannot implement x() in Baz
[error] public BoxedUnit x() {
[error] ^
[error] return type BoxedUnit is not compatible with void
Und wenn ich den abstrakten Klasse-dass-Delegierten-to-super-Trait Trick versuchen:
abstract class Qux extends Baz {
override def x() = super.x()
}
Und dann:
public class JQux extends Qux {}
Es ist sogar noch schlimmer:
[error] /home/travis/tmp/so/js/newsutff/JQux.java:1: error: JQux is not abstract and does not override abstract method x() in Foo
[error] public class JQux extends Qux {}
[error] ^
(Beachten Sie, dass diese Definition von JQux
würde gut funktionieren, wenn Baz
wurde nicht erweitert Foo[Unit]
.)
Wenn man sich anschaut, was javap
sagt über Qux
, es ist nur komisch:
public abstract class Qux implements Baz {
public void x();
public java.lang.Object x();
public Qux();
}
denke ich, sowohl die hier Probleme mit Baz
und Qux
scalac Fehler sein, aber ist es eine Abhilfe? Ich interessiere mich nicht wirklich für den Baz
Teil, aber gibt es irgendeinen Weg, den ich von Qux
in Java erben kann?
Vielleicht "Bug" ist das falsche Wort - ich meine etwas mehr wie "Verrat an einer ziemlich vernünftigen Erwartung". Mit dem 'BoxedUnit.UNIT'-Trick kann ich eine generische 'Unit'-Methode implementieren, warum bricht dann das Hinzufügen einer Vererbungsebene das? Es ist nicht so, dass es die Methode in irgendeiner Weise weniger generisch macht. –
Es gibt nicht eine Vererbungsebene, sondern eine neue 'public void x()' Methode, und javac ist nicht glücklich darüber. Es glaubt, dass _das_ die Eigenschaft ist, die das Merkmal implementiert, obwohl es eine BoxedUnit-Version gibt. Es sucht nach einer Signatur von BoxedUnit x() ', was es selbst erzeugen würde. –
(Es gibt eine 'BoxedUnit'-Version herum, aber es ist getippt als' Objekt', meine ich.) –