11
object ScalaTrueRing {
  def rule = println("To rule them all")
}

このコードは Java バイト コードにコンパイルされます。逆コンパイルすると、同等の Java コードは次のようになります。

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;
/*    */   }
/*    */ }

これは 2 つのクラスにコンパイルされます。Scala.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$();
    }
}

また、2 つのクラスにコンパイルされます。

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

4

3 に答える 3

12

objectScalaでは、実際には一級市民であることを理解することが重要です。これは、他のオブジェクトと同じように渡すことができる実際のインスタンスです。例:

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 )

静的メソッドとは異なり、シングルトンオブジェクトは完全なポリモーフィックな動作をします。doSomething実際には、デフォルトの実装ではなく、オーバーライドhelloされbyeたメソッドを呼び出します。

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

したがって、object実装は必ず適切なクラスである必要があります。ただし、Javaとの相互運用性のために、コンパイラーは、クラスの一意のインスタンス()に転送する静的メソッドも生成します(MODULE$JavaTrueRing.rule()を参照)。このようにして、Javaプログラムは、通常の静的メソッドとしてシングルトンオブジェクトのメソッドにアクセスできます。ここで、scalaが静的メソッドフォワーダーをインスタンスメソッドと同じクラスに配置しない理由を疑問に思うかもしれません。これにより、次のようになります。

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

これがそれほど単純ではない主な理由は、JVMでは、同じクラスに同じシグニチャを持つインスタンスメソッドと静的メソッドを含めることができないためだと思います。ただし、他の理由があるかもしれません。

于 2012-10-08T15:55:43.090 に答える
3

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

于 2012-10-08T15:37:53.457 に答える
1

このブログ エントリ「Scala Compiles to Java の概要」があなたの質問に答えるはずです。

通常、ClassName$.class は内部クラスの結果です。Scala は明らかにわずかに異なります。

于 2012-10-08T14:45:05.700 に答える