Why is a Scala companion object compiled into two classes(both Java and .NET compilers)?

别来无恙 提交于 2019-12-01 03:50:25

It is important to understand that in scala, an object actually is a first class citizen: it is an actual instance that can be passed around as any other object. By example:

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 )

Unlike with static methods, our singleton object has full polymorphic beheviour. doSomething will indeed call our overriden hello and bye methods, and not the default implementations:

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

So the object implementation must necessarily be a proper class. But for interoperability with java, the compiler also generates static methods that just forward to the unique instance (MODULE$) of the class (see JavaTrueRing.rule()). This way, a java program can access the methods of the singleton object as a normal static method. Now you might ask why scala does not put the static method forwarders in the same class as the instance methods. This would give us something like:

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

I believe that the main reason why this can't be as simple is because in the JVM you cannot have in the same class an instance method and a static method wth the same signature. There might be other reasons though.

Paraphrasing from "Programming in Scala" - Because a scala companion object (singleton object) is more than just a holder of static methods. By being an instance of a different Java class, it allows the developer to extend singleton objects and mix-in traits. This cannot be done with static methods.

This Blog entry "A Look at How Scala Compiles to Java" should answer your question

Typically ClassName$.class are results of inner classes - Scala is obviously slightly different.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!