2010-07-19 14 views
21

Sto provando a inserire un codice Scala nella mia app Java esistente. (Quindi, detto, voglio un po 'più divertente).Come si chiama un metodo Scala singleton da Java?

creo una roba Singleton a Scala

ScalaPower.scala 

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

Ora, all'interno OldJava.java

class OldJava { 
    public void demo(){ 
    System.out.println(?) 
    } 
} 

Cosa devo compilare ? in modo che Java chiamerà il metodo showMyPower? Ho provato sia org.fun.ScalaPower.showMyPower(10) e org.fun.ScalaPower.getInstance().showMyPower(10) ma nessuno funziona.

(decompilare il file di classe utilizzando Jad mi mostra nulla, ma il codice sciocchezza.)

Edit ho rimuovere la dichiarazione class ScalaPower e scala producono il metodo statico come previsto. (chiamare a org.fun.ScalaPower.showMyPower(10) funziona solo).

chiedo se è un bug nel compilatore Scala o no

+1

Che dire 'org.fun.ScalaPower.showMyPower (10)'? – OscarRyz

+0

Ouch, mio ​​male. Hai dimenticato di cambiare lo spazio dei nomi. Aggiornata la domanda già. Grazie. –

+1

A proposito, puoi scrivere "0 fino all'ora" invece di "0 all'ora-1". –

risposta

9

Credo che questo copre indirettamente:

Companion Oggetti e Java statici Metodi

C'è una cosa da sapere circa oggetti da compagnia. Ogni volta che si definisce un metodo principale da utilizzare come punto per un'applicazione, Scala richiede di inserirlo in un oggetto. Tuttavia, al momento della stesura di questo documento, i metodi principali non possono essere definiti in un oggetto companion . A causa dei dettagli di implementazione di nel codice generato , la JVM non troverà il metodo principale . Questo problema potrebbe essere risolto in una versione futura. Per ora, , è necessario definire qualsiasi metodo principale in un oggetto singleton (ad esempio, un oggetto "non companion" ) [ScalaTips]. Considerare il seguente esempio di una classe Persona semplice e di un oggetto companion che tenta di definire main.

Come trovate qui: http://programming-scala.labs.oreilly.com/ch06.html

In breve, perché l'oggetto è un oggetto associato (ha una classe compagna), non si può chiamare come ci si aspetta. Come hai scoperto se ti sbarazzi della classe, funzionerà.

+2

Questo non è più vero. Da qualche parte tra quando è stato scritto e quando Scala 2.8 è stato rilasciato, i modelli di generazione del codice di inoltro sono stati corretti per consentire i metodi principali in companion. –

+0

Oooh, eccellente. Il libro ha lasciato intendere che sarebbe stato cambiato, ma non ha detto per 2.8 (e non vedevano l'ora che arrivassero le 2.8). Detto questo l'interrogante originale non fornisce la sua versione, e dal suo "Modifica rimuovo la dichiarazione ScalaPower della classe e scala produce il metodo statico come previsto". sembra ancora che potrebbe essere stato il problema. –

+0

Grazie. Questo spiega la mia situazione. Sto passando a scala 2.8 in questo momento. Diavolo, il plug-in di eclipse scala fa ancora schifo. –

3

Tenete a mente che lo strumento stock javap può essere utilizzato per vedere ciò che il compilatore Scala produce. Ovviamente non risponde alla tua domanda, ma quando ciò che ti serve è solo per ricordare i modelli di generazione del codice, è sufficiente.

+0

Grazie. Ci proverò quando torno a casa. (Al lavoro ora) –

10

Quali erano gli errori che si stavano ottenendo? Utilizzando il campione Scala e la seguente classe Java:

cat test.java:


import org.fun.*; 

public class test { 
    public static void main(String args[]) { 
     System.out.println("show my power: " + ScalaPower.showMyPower(3));  
    } 
} 

E eseguirlo come segue:

java -cp .:<path-to/scala/install-dir>/lib/scala-library.jar test

dà la mia uscita:

show my power: 0, 1, 2

+1

Hmm, è strano. Il mio codice non è nemmeno compilato. Sta dicendo "Simbolo" showMyPower "non trovato" (anche se il plugin IDEA Scala lo capisce e mi offre un completamento automatico) –

+0

Rilevo che in realtà il metodo 'showMyPower' è dichiarato in Scala $, non in Scala. Quale versione di Scala stai usando che rende questo codice compilabile? Sto usando 2.7.5 –

+0

Ouch, 'org.fun.ScalaPower $ .MODULE $ .showMyPower' è davvero il metodo corretto che dovrei chiamare, What the heck? –

1

Dopo aver fatto

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

ScalaPower.showMyPower(10) funziona come previsto.

14

Di solito è meglio accedere al singleton direttamente dalla propria classe.

In questo caso:

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

Senza entrare troppo nei dettagli di implementazione, Scala differenzia gli spazi dei nomi tra oggetto e classe/Trait. Ciò significa che possono usare lo stesso nome. Tuttavia, un oggetto ha una classe e pertanto necessita di un nome distorto sulla JVM. Le attuali convenzioni di Scala consistono nell'aggiungere un $ alla fine del nome del modulo (per i moduli di livello superiore). Se l'oggetto è definito in una classe, credo che la convenzione sia OuterClass $ ModuleName $. Per forzare la proprietà singleton del modulo ScalaPower, esiste anche un membro MODULE $ statico della classe $ ModuleName. Questo viene inizializzato in fase di caricamento in classe, assicurando che vi sia una sola istanza. Un effetto collaterale di questo è che si dovrebbe non fare alcun tipo di blocco nel costruttore di un modulo.

In ogni caso, Scala ha anche incorporato un meccanismo di "statiche avanzate per Java". Qui è dove scrive metodi statici sulla classe ScalaPower che chiama semplicemente ScalaPower $ .MODULE $ .someMethod(). Se si definisce anche una classe companion, i server di inoltro che potrebbero essere generati sono limitati, in quanto non è consentito avere conflitti di denominazione con metodi statici e di livello di istanza sulla JVM. Penso che in 2.8.0 questo significa che se hai un oggetto compagno, perdi i tuoi statici.

In questo caso, una "best practice" consiste nell'utilizzare sempre il riferimento $ .MODULE $ ScalaPower invece di un server di inoltro statico, poiché il server di inoltro potrebbe scomparire con modifiche alla classe ScalaPower.

EDIT: Typo

+0

Il codice qui ha un errore di battitura in MODULO $ –

Problemi correlati