加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

为什么Scala伴侣对象被编译为两个类(Java和.NET编译器)?

发布时间:2020-12-16 19:12:31 所属栏目:安全 来源:网络整理
导读:object ScalaTrueRing { def rule = println("To rule them all")} 这段代码将被编译成java字节码,如果我反编译它,那么等效的Java代码就像这样: public final class JavaTrueRing{ public static final void rule() { ScalaTrueRing..MODULE$.rule(); }}/*
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;
/*    */   }
/*    */ }

它被编译成两个类,如果我使用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$();
    }
}

它也被编译成两个类.

为什么Scala编译器(用于Java的编译器和用于.NET的编译器)执行此操作?
为什么不在静态规则方法中调用println方法呢?

解决方法

重要的是要理解,在scala中,对象实际上是一等公民:它是一个可以作为任何其他对象传递的实际实例.
举例:

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

因此,对象实现必须是一个合适的类.但是为了与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中你不能在同一个类中拥有一个实例方法和一个静态方法具有相同的签名.可能还有其他原因.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读