Java-Interoperabilitätsprobleme mit Scala-Generika und Boxen

8

Angenommen, ich habe dieses Scala-Merkmal:

%Vor%

Die Bereitstellung einer Java-Implementierung ist einfach:

%Vor%

Beginnen wir nun mit einem generischen Merkmal:

%Vor%

Der obige Ansatz funktioniert nicht, da die Einheit x returns jetzt eingerahmt ist, aber die Problemumgehung ist einfach genug:

%Vor%

Angenommen, ich habe eine Implementierung mit x auf der Scala-Seite definiert:

%Vor%

Ich weiß, dass ich dieses x von Java nicht sehen kann, also definiere ich mein eigenes:

%Vor%

Aber das explodiert:

%Vor%

Und wenn ich den Trick der abstrakten Klasse, der Delegierten auf Super-Charakter, versuche:

%Vor%

Und dann:

%Vor%

Es ist noch schlimmer:

%Vor%

(Beachten Sie, dass diese Definition von JQux nur funktionieren würde, wenn Baz Foo[Unit] nicht erweitert hätte.)

Wenn du dir ansiehst, was javap über Qux sagt, ist es einfach seltsam:

%Vor%

Ich denke, die Probleme hier mit Baz und Qux müssen Scalac-Bugs sein, aber gibt es einen Workaround? Ich interessiere mich nicht wirklich für den Baz -Teil, aber gibt es irgendeine Möglichkeit, die ich von Qux in Java erben kann?

    
Travis Brown 30.10.2014, 00:28
quelle

1 Antwort

8

Sie sind keine Scalac-Käfer; es ist, dass der Scala-Compiler in Ihrem Namen hart daran arbeitet, den Unterschied zwischen Prozeduren und Methoden zu packen, und der Java-Compiler nicht.

Für die Effizienz und Java-Kompatibilität werden Methoden, die Unit nicht-generisch zurückgeben, tatsächlich als Prozeduren implementiert (d. h. der Rückgabetyp ist void ). Dann wird die generische Implementierung implementiert, indem die void version aufgerufen und BoxedUnit zurückgegeben wird.

%Vor%

Das Problem ist, dass javac dasselbe für Sie mit spezifischen vs. generischen Object -abgeleiteten Rückgabetypen macht, aber nicht die Object - void -Kreuzung versteht.

Das ist eine Erklärung. Es gibt eine Problemumgehung, obwohl es die Scala-Hierarchie verkompliziert:

%Vor%

Nun haben Sie Scala gezwungen, die Möglichkeit eines nicht-genau- Unit Rückgabetyps zu berücksichtigen, damit BoxedUnit für die Rückgabe beibehalten wird; und Baz verwirft diese Möglichkeit, aber es erzeugt kein neues void x() , um Java zu verwirren.

Das ist fragil, um es milde auszudrücken. Es kann aber auch ein Problem für die Java und Scala Teams sein: Java ist nicht glücklich, solange die BoxedUnit Version da ist; es wird aktiv durch die void version genervt. (Sie können eine abstrakte Klasse mit beiden erzeugen, indem Sie zweimal von Foo erben; da es nicht funktioniert, sind die Details unwichtig.) Scala könnte es alleine schaffen, indem es geänderten Bytecode mit einer zusätzlichen BoxedUnit-Methode überall dort ausgibt, wo Java es erwartet. ..nicht sicher.

    
Rex Kerr 30.10.2014, 01:58
quelle

Tags und Links