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

este pedazo de código serán compilados en código de bytes de Java, si descompilarlo, a continuación, el código equivalente Java es similar a esto:¿Por qué un objeto complementario de Scala se compila en dos clases (compiladores Java y .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; 
/* */ } 
/* */ } 

es compilado en dos clases, y si uso Scala .net compilador, que va a ser compilado en código MSIL, y el código C# equivalente es la siguiente:

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$(); 
    } 
} 

también se recopiló en dos clases.

¿Por qué los compiladores Scala (el de Java y el de .NET) hacen esto? ¿Por qué no solo llama al método println en el método de regla estática?

+0

Entonces, ¿de dónde viene la clase 'JavaTrueRing $'? –

+0

@The Elite Gentleman su verdadero nombre es ScalaTrueRing $, cambié el nombre para mostrar explícitamente que es código Java. Descompilé el archivo de clase y lo obtuve. – CuiPengFei

Respuesta

8

Es importante entender que en scala, un object en realidad es un ciudadano de primera clase: es una instancia real que se puede pasar como cualquier otro objeto. Por ejemplo:

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) 

A diferencia de los métodos estáticos, nuestro objeto Singleton tiene plena beheviour polimórfica. doSomething de hecho se llame a nuestras sobrecargadas hello y bye métodos, y no las implementaciones por defecto:

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

Así que la aplicación object debe ser necesariamente una clase adecuada. Pero para la interoperabilidad con java, , el compilador también genera métodos estáticos que simplemente reenvían a la instancia única (MODULE$) de la clase (ver JavaTrueRing.rule()). De esta manera, un programa java puede acceder a los métodos del objeto singleton como un método estático normal. Ahora puede preguntar por qué Scala no coloca los reenviadores de métodos estáticos en la misma clase que los métodos de instancia. Esto nos daría algo así como:

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(); 
    } 
} 

Creo que la razón principal por la que esto no puede ser tan simple es porque en la JVM no se puede tener en la misma clase un método de instancia y un método estático wth de la misma firma. Sin embargo, puede haber otras razones.

1

Este Blog entry "A Look at How Scala Compiles to Java" debe responder a su pregunta

Normalmente NombredeClase $ .class son resultados de las clases internas - Scala es, obviamente, un poco diferente.

+1

esa publicación de blog explica qué hace el compilador de Scala, pero no explica por qué. ¿Por qué el compilador Scala no solo llama al método println en el método de regla estática? – CuiPengFei

3

Parafraseando desde "Programación en Scala" - Debido a que un objeto complementario scala (objeto singleton) es más que un simple titular de métodos estáticos. Al ser una instancia de una clase Java diferente, le permite al desarrollador extender objetos únicos y rasgos mixtos. Esto no se puede hacer con métodos estáticos.

Cuestiones relacionadas