Wie ruft man eine Scala-Singleton-Methode aus Java auf?
-
17-09-2020 - |
Frage
Ich versuche, Scala-Code in meine vorhandene Java-App einzufügen.(Also, wie gesagt, ich möchte etwas mehr Spaß).
Ich erstelle ein Singleton-Zeug in Scala
ScalaPower.scala
package org.fun
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
Jetzt in OldJava.java
class OldJava {
public void demo(){
System.out.println(?)
}
}
Was soll ich ausfüllen? ?
damit Java die showMyPower-Methode aufruft?Ich habe beides ausprobiert org.fun.ScalaPower.showMyPower(10)
Und org.fun.ScalaPower.getInstance().showMyPower(10)
aber keines funktioniert.
(Dekompilieren Sie die Klassendatei mit Jad und zeigen Sie mir nichts als unsinnigen Code.)
BearbeitenIch entferne die class ScalaPower
Deklaration und Scala erzeugen wie erwartet die statische Methode.(Ruf an org.fun.ScalaPower.showMyPower(10)
funktioniert einfach).
Ich frage mich, ob es ein Fehler im Scala-Compiler ist oder nicht
Lösung
Ich denke, das deckt es indirekt ab:
Begleitobjekte und statische Java -Methoden
Es gibt noch eine Sache zu wissen über Begleitobjekte.Wenn Sie eine Hauptmethode definieren, die als Einstiegspunkt für eine Anwendung verwendet werden soll, müssen Sie sie in ein Objekt einfügen.Zum Zeitpunkt dieses Schreibens können jedoch die Hauptmethoden in einem Begleitobjekt nicht definiert werden.Aufgrund von Implementierungsdetails im generierten Code findet die JVM die Hauptmethode nicht.Dieses Problem kann in einer zukünftigen Veröffentlichung gelöst werden.Im Moment müssen Sie jede Hauptmethode in einem Singleton-Objekt (dh einem „Nicht-Kompanon" -Objekt) [scalatips] definieren.Betrachten Sie das folgende Beispiel für ein einfaches Personen- und Begleitobjekt, das versucht, Main zu definieren.
Wie hier gefunden: http://programming-scala.labs.oreilly.com/ch06.html
Kurz gesagt, da Ihr Objekt ein Begleitobjekt ist (eine Begleitklasse hat), können Sie es nicht wie erwartet aufrufen.Wie Sie festgestellt haben, wird es funktionieren, wenn Sie die Klasse loswerden.
Andere Tipps
Normalerweise ist es besser, direkt von seiner eigenen Klasse aus auf den Singleton zuzugreifen.
In diesem Fall:
org.fun.ScalaPower$.MODULE$.showMyPower(10);
Ohne zu sehr auf die Implementierungsdetails einzugehen, unterscheidet Scala Namensräume zwischen Objekt und Klasse/Merkmal.Das bedeutet, dass sie denselben Namen verwenden können.Ein Objekt hat jedoch eine Klasse und benötigt daher einen verstümmelten Namen in der JVM.Die aktuellen Scala-Konventionen bestehen darin, am Ende des Modulnamens ein $ hinzuzufügen (für Module der obersten Ebene).Wenn das Objekt in einer Klasse definiert ist, lautet die Konvention meiner Meinung nach OuterClass$ModuleName$.Um die Singleton-Eigenschaft des ScalaPower-Moduls zu erzwingen, gibt es auch ein statisches MODULE$-Mitglied der ModuleName$-Klasse.Dies wird zum Zeitpunkt des Ladens der Klasse initialisiert, um sicherzustellen, dass es nur eine Instanz gibt.Ein Nebeneffekt davon ist, dass Sie es tun sollten nicht Führen Sie irgendeine Art von Sperrung im Konstruktor eines Moduls durch.
Auf jeden Fall hat Scala auch einen statischen Weiterleitungsmechanismus integriert, der die Dinge für Java schöner macht.Hier werden statische Methoden der ScalaPower-Klasse geschrieben, die lediglich ScalaPower$.MODULE$.someMethod() aufrufen.Wenn Sie auch eine Begleitklasse definieren, sind die generierten Weiterleitungen begrenzt, da Sie keine Namenskonflikte mit statischen Methoden und Methoden auf Instanzebene in der JVM haben dürfen.Ich denke, in 2.8.0 bedeutet das, dass Sie Ihre statischen Weiterleitungen verlieren, wenn Sie ein Begleitobjekt haben.
In diesem Fall wäre es eine „Best Practice“, immer die ScalaPower$.MODULE$-Referenz anstelle einer statischen Weiterleitung zu verwenden, da die Weiterleitung bei Änderungen an der ScalaPower-Klasse verschwinden könnte.
BEARBEITEN:Tippfehler
Welche Fehler sind bei Ihnen aufgetreten?Verwenden Sie Ihr Scala-Beispiel und die folgende Java-Klasse:
cat test.java
:
import org.fun.*;
public class test {
public static void main(String args[]) {
System.out.println("show my power: " + ScalaPower.showMyPower(3));
}
}
Und führe es wie folgt aus:
java -cp .:<Pfad zu/scala/installationsverzeichnis>/lib/scala-library.jar test
gibt mir die Ausgabe:
show my power: 0, 1, 2
Bedenken Sie, dass die Aktie javap
Mit dem Tool können Sie sehen, was der Scala-Compiler produziert.Natürlich wird Ihre Frage dadurch nicht direkt beantwortet, aber wenn Sie lediglich an die Codegenerierungsmuster erinnert werden möchten, ist dies ausreichend.
Danach
class ScalaPower
object ScalaPower{
def showMyPower(time:Int) = {
(0 to time-1).mkString(", ")
}
}
ScalaPower.showMyPower(10)
Funktioniert wie erwartet.