2012-10-08 17 views
6
object ScalaTrueRing { 
    def rule = println("To rule them all") 
} 

questo pezzo di codice saranno raccolte in codice Java byte, se mi decompilare, allora il codice Java equivalente è simile a questo:Perché un oggetto compagno Scala è compilato in due classi (sia compilatori Java che .NET)?

public final class JavaTrueRing 
{ 
    public static final void rule() 
    { 
    ScalaTrueRing..MODULE$.rule(); 
    } 
} 


/* */ public final class JavaTrueRing$ 
/* */ implements ScalaObject 
/* */ { 
/* */ public static final MODULE$; 
/* */ 
/* */ static 
/* */ { 
/* */  new(); 
/* */ } 
/* */ 
/* */ public void rule() 
/* */ { 
/* 11 */  Predef..MODULE$.println("To rule them all"); 
/* */ } 
/* */ 
/* */ private JavaTrueRing$() 
/* */ { 
/* 10 */  MODULE$ = this; 
/* */ } 
/* */ } 

è compilato in due classi, e se uso Scala .net compilatore, che sarà essere compilato in codice MSIL, e il codice C# equivalente è come questo:

public sealed class ScalaTrueRing 
{ 
    public static void rule() 
    { 
     ScalaTrueRing$.MODULE$.rule(); 
    } 
} 

[Symtab] 
public sealed class ScalaTrueRing$ : ScalaObject 
{ 
    public static ScalaTrueRing$ MODULE$; 
    public override void rule() 
    { 
     Predef$.MODULE$.println("To rule them all"); 
    } 
    private ScalaTrueRing$() 
    { 
     ScalaTrueRing$.MODULE$ = this; 
    } 
    static ScalaTrueRing$() 
    { 
     new ScalaTrueRing$(); 
    } 
} 

e 'anche compilato in due classi.

Perché i compilatori Scala (quello per Java e quello per .NET) lo fanno? Perché non chiama semplicemente il metodo println nel metodo della regola statica?

+0

Quindi, da dove viene la classe 'JavaTrueRing $'? –

+0

@The Elite Gentleman il suo vero nome è ScalaTrueRing $, ho cambiato il nome per mostrare esplicitamente che si tratta di codice java. Ho decompilato il file di classe e l'ho capito. – CuiPengFei

risposta

8

È importante capire che in scala, un object è effettivamente un cittadino di prima classe: è un'istanza reale che può essere passata come qualsiasi altro oggetto. Di Esempio:

trait Greetings { 
    def hello() { println("hello") } 
    def bye() { println("bye") } 
} 

object FrenchGreetings extends Greetings { 
    override def hello() { println("bonjour") } 
    override def bye() { println("au revoir") } 
} 

def doSomething(greetings: Greetings) { 
    greetings.hello() 
    println("... doing some work ...") 
    greetings.bye() 
} 

doSomething(FrenchGreetings) 

differenza con metodi statici, il nostro oggetto Singleton ha piena beheviour polimorfico. doSomething sarà infatti chiamare i nostri sovrascritto hello e bye metodi e non le implementazioni di default:

bonjour 
... doing some work ... 
au revoir 

Così l'attuazione object deve necessariamente essere una classe propria. Ma per l'interoperabilità con java, , il compilatore genera anche metodi statici che inoltrano semplicemente all'istanza univoca (MODULE$) della classe (vedere JavaTrueRing.rule()). In questo modo, un programma java può accedere ai metodi dell'oggetto singleton come un normale metodo statico. Ora si potrebbe chiedere perché scala non inserisce gli inoltro dei metodi statici nella stessa classe dei metodi di istanza. Questo ci darebbe qualcosa di simile:

public final class JavaTrueRing implements ScalaObject { 
    public static final MODULE$; 

    static { 
    new JavaTrueRing(); 
    } 

    public void rule() { 
    Predef.MODULE$.println("To rule them all"); 
    } 

    private JavaTrueRing() { 
    MODULE$ = this; 
    } 

    // Forwarders 
    public static final void rule() { 
    MODULE$.rule(); 
    } 
} 

Credo che la ragione principale per cui questo non può essere semplice è perché nella JVM non si può avere nella stessa classe un metodo di istanza e un metodo statico wth stesso firma. Ci potrebbero essere altri motivi.

1

Questo Blog entry "A Look at How Scala Compiles to Java" dovrebbe rispondere alla tua domanda

Tipicamente ClassName $ .class sono risultati di classi interne - Scala è ovviamente leggermente diverso.

+1

che il post sul blog spiega cosa fa il compilatore Scala, ma non spiega perché. Perché il compilatore Scala non chiama semplicemente il metodo println nel metodo della regola statica? – CuiPengFei

3

Parafrasando da "Programmazione in Scala" - Perché un oggetto scala compagno (oggetto singleton) è più di un semplice detentore di metodi statici. Essendo un'istanza di una diversa classe Java, consente allo sviluppatore di estendere oggetti singleton e tratti di mix-in. Questo non può essere fatto con metodi statici.