26 Stimmen

Wie ruft man eine Scala-Singleton-Methode von Java aus auf?

Ich versuche, einige Scala-Code in meine bestehende Java-App zu injizieren. (Also, wobei gesagt, ich will etwas mehr Spaß).

Ich erstelle ein singleton stuff 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 Methode showMyPower aufruft? Ich habe beides versucht org.fun.ScalaPower.showMyPower(10) y org.fun.ScalaPower.getInstance().showMyPower(10) aber keine funktioniert.

(Das Dekompilieren der Klassendatei mit Jad zeigt mir nichts als unsinnigen Code).

bearbeiten Ich entferne die class ScalaPower Deklaration und Scala erzeugen die statische Methode wie erwartet. (Aufruf von org.fun.ScalaPower.showMyPower(10) funktioniert einfach).

Ich frage mich, ob es ein Fehler im Scala-Compiler ist oder nicht

1 Stimmen

Was ist mit org.fun.ScalaPower.showMyPower(10) ?

0 Stimmen

Autsch, mein Fehler. Ich habe vergessen, den Namensraum zu ändern. Habe die Frage bereits aktualisiert. Danke dafür.

1 Stimmen

Übrigens, Sie können schreiben 0 until time anstelle von 0 to time-1 .

22voto

jsuereth Punkte 5534

Normalerweise ist es besser, auf das Singleton direkt von seiner eigenen Klasse aus zuzugreifen.

In diesem Fall:

org.fun.ScalaPower$.MODULE$.showMyPower(10);

Ohne zu sehr auf die Implementierungsdetails einzugehen, unterscheidet Scala zwischen Namespaces für Object und Class/Trait. Das bedeutet, dass sie denselben Namen verwenden können. Ein Objekt hat jedoch eine Klasse und benötigt daher einen geänderten Namen auf der JVM. Die aktuelle Scala-Konvention ist es, ein $ am Ende des Modulnamens hinzuzufügen (für Top-Level-Module). Wenn das Objekt in einer Klasse definiert ist, lautet die Konvention meines Wissens nach OuterClass$Modulname$. Um die Singleton-Eigenschaft des ScalaPower-Moduls zu erzwingen, gibt es auch ein statisches MODULE$-Mitglied der Klasse Modulname$. Dieses wird beim Laden der Klasse initialisiert, um sicherzustellen, dass es nur eine Instanz gibt. Ein Nebeneffekt hiervon ist, dass Sie no jede Art von Sperrung im Konstruktor eines Moduls vornehmen.

In jedem Fall hat Scala auch einen Mechanismus für statische Weiterleitungen eingebaut, der die Dinge für Java schöner macht. Hier werden statische Methoden in die ScalaPower-Klasse geschrieben, die einfach ScalaPower$.MODULE$.someMethod() aufrufen. Wenn Sie auch eine Begleitklasse definieren, sind die Weiterleitungen, die generiert werden können, begrenzt, da Sie keine Namenskonflikte mit statischen und Instanzmethoden auf der JVM haben dürfen. Ich denke, in 2.8.0 bedeutet dies, dass Sie Ihre statischen Forwarder verlieren, wenn Sie ein Companion-Objekt haben.

In diesem Fall wäre es eine "Best Practice", immer die ScalaPower$.MODULE$-Referenz anstelle eines statischen Forwarders zu verwenden, da der Forwarder bei Änderungen an der ScalaPower-Klasse verschwinden könnte.

EDIT: Tippfehler

10voto

Arjan Blokzijl Punkte 6808

Was waren die Fehler, die Sie erhalten haben? 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ühren Sie es wie folgt aus:

java -cp .:<_path-to/scala/install-dir_>/lib/scala-library.jar test

gibt mir die Ausgabe:

show my power: 0, 1, 2

1 Stimmen

Hmm, das ist seltsam. Mein Code lässt sich nicht einmal kompilieren. Er sagt "Symbol 'showMyPower' not found" (obwohl IDEA Scala Plugin es versteht und mir eine Autovervollständigung anbietet)

0 Stimmen

Ich habe herausgefunden, dass die Methode showMyPower wird innerhalb von Scala$ deklariert, nicht von Scala. Welche Version von Scala verwenden Sie, die diesen Code kompilierbar macht? Ich verwende 2.7.5

0 Stimmen

Autsch, org.fun.ScalaPower$.MODULE$.showMyPower in der Tat die richtige Methode ist, die ich aufrufen sollte, Was soll's?

10voto

Ry4an Brase Punkte 77642

Ich denke, das deckt sich indirekt damit:

Companion-Objekte und Java Static Methoden

Es gibt noch eine weitere Sache, die man über Begleitobjekte. Wann immer Sie eine eine Hauptmethode definieren, die als Einstiegspunkt Einstiegspunkt für eine Anwendung zu verwenden, verlangt Scala verlangt von Ihnen, dass Sie sie in ein Objekt packen. Zum Zeitpunkt der Erstellung dieses Artikels können jedoch können Hauptmethoden nicht in einem Begleitobjekt definiert werden. Aufgrund von Implementierungsdetails in dem generierten Code, findet die JVM die Hauptmethode nicht finden. Dieses Problem wird möglicherweise in einer zukünftigen Version behoben werden. Im Moment müssen Sie jede Hauptmethode in einem Singleton Objekt (d.h. ein "nicht-kompatiblen" Objekt) definieren [ScalaTips]. Betrachten Sie das folgende Beispiel einer einfachen Person Klasse und Begleiter Objekt, das versucht, main zu definieren.

Wie hier zu finden: http://programming-scala.labs.oreilly.com/ch06.html

Kurz gesagt, weil Ihr Objekt ein Begleitobjekt ist (eine Begleitklasse hat), können Sie es nicht so aufrufen, wie Sie es erwarten. Wie Sie festgestellt haben, wird es funktionieren, wenn Sie die Klasse loswerden.

3 Stimmen

Dies ist nicht mehr der Fall. Irgendwann zwischen dem Zeitpunkt, an dem das geschrieben wurde, und dem Zeitpunkt, an dem Scala 2.8 veröffentlicht wurde, wurden die Muster für die Erzeugung von Weiterleitungscode festgelegt, um Hauptmethoden in Begleitern zu ermöglichen.

0 Stimmen

Oh, ausgezeichnet. Im Buch wurde angedeutet, dass sie sich eine Änderung wünschen, aber nicht für 2.8 (und sie haben sich sehr auf 2.8 gefreut). Das heißt, der ursprüngliche Fragesteller gibt seine Version nicht an, und aus seinem "Edit I remove the class ScalaPower declaration and scala produce the static method as expected.

0 Stimmen

Danke. Das erklärt meine Situation. Ich bin gerade dabei, auf Scala 2.8 umzusteigen. Verdammt, das Eclipse Scala-Plugin ist immer noch schlecht.

3voto

Randall Schulz Punkte 26072

Denken Sie daran, dass die Aktie javap Tool kann verwendet werden, um zu sehen, was der Scala-Compiler erzeugt. Es beantwortet Ihre Frage natürlich nicht direkt, aber wenn Sie nur an die Muster der Codegenerierung erinnert werden wollen, ist es ausreichend.

1voto

Jus12 Punkte 17438

Nach der Durchführung

class ScalaPower 
object ScalaPower{
  def showMyPower(time:Int) = {
    (0 to time-1).mkString(", ")
  }
}

ScalaPower.showMyPower(10) funktioniert wie erwartet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X