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

この作品は、私はそれを逆コンパイル場合は、同等のJavaコードは次のようになり、Javaバイトコードにコンパイルされます。Scalaコンパニオンオブジェクトが2つのクラス(Javaと.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; 
/* */ } 
/* */ } 

私はスカラ座を使用している場合、それは二つのクラスにコンパイルされ、そしてです.NETコンパイラは、MSILコードにコンパイルされます、と同等のC#のコードは、このようなものです:

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

また二つのクラスにコンパイルされています。

なぜScalaコンパイラ(Java用と.NET用)がこれを行うのですか? 静的ルールメソッドでprintlnメソッドを呼び出すのはなぜですか?

+0

JavaTrueRing $はどのクラスから来ていますか? –

+0

@エリート紳士それは本当の名前はScalaTrueRing $です、私は明示的にそれがJavaコードであることを示すために名前を変更しました。私はクラスファイルを逆コンパイルして取得しました。 – CuiPengFei

答えて

8

スケーラではobjectが実際にファーストクラスの市民であることを理解することが重要です。実際のインスタンスであり、他のオブジェクトとして渡すことができます。例によって :静的メソッドとは異なり

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) 

は、私たちのシングルトンオブジェクトは、完全な多型beheviourを持っています。

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

だから object実装は、必ずしも適切なクラスでなければなりません: doSomethingは確かに私たちのオーバーライド hellobye方法ではなく、デフォルトの実装を呼び出します。しかし、Javaとの相互運用性のために、 コンパイラは、クラスのユニークなインスタンス( MODULE$)に転送する静的メソッドも生成します(JavaTrueRing.rule()を参照)。 このようにして、Javaプログラムは、通常の静的メソッドとしてシングルトンオブジェクトのメソッドにアクセスできます。 これで、scalaが静的メソッドのフォワーダをインスタンスメソッドと同じクラスに配置しない理由を尋ねることができます。私はJVMにあなたが同じクラスにインスタンスメソッドと同じWTH静的メソッドを持つことができないので、これはのように単純なことができない主な理由であると信じている

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

:これは私たちのようなものを与えるだろう署名。しかし、他の理由があるかもしれません。

1

このBlog entry "A Look at How Scala Compiles to Java"

は一般的にクラス名の$ .classファイルは内部クラスの結果であり、あなたの質問に答える必要があります - Scalaは明らかにわずかに異なっています。

+1

そのブログ記事はScalaコンパイラのしくみを説明していますが、その理由を説明していません。なぜScalaコンパイラは静的ルールメソッドでprintlnメソッドを呼び出すだけではありませんか? – CuiPengFei

3

"Scalaのプログラミング"からの言い換え - スカラコンパニオンオブジェクト(シングルトンオブジェクト)は単なる静的メソッドのホルダー以上のものです。別のJavaクラスのインスタンスであることにより、開発者はシングルトンオブジェクトやミックスインの特性を拡張することができます。これは静的メソッドでは実行できません。

関連する問題