开发者

Singletons as Synthetic classes in Scala?

开发者 https://www.devze.com 2023-02-26 20:00 出处:网络
I am reading Programming in Scala, and I don\'t understand the following sentence (pdf p.112): Each singleton object is implemented as an instance of a开发者_如何学Python synthetic class referenced

I am reading Programming in Scala, and I don't understand the following sentence (pdf p.112):

Each singleton object is implemented as an instance of a开发者_如何学Python synthetic class referenced from a static variable, so they have the same initialization semantics as Java statics.

Does this mean the if I have a singleton FooBar in scala, the compiler will create a class named FooBar$?

Also what does the author mean by "referenced from a static variable"? Is there a hidden static variable somewhere holding a reference to some FooBar$ class?

I appreciate any help here.


The chapter 31 of the same "Programming in Scala" is more precise:

Java has no exact equivalent to a singleton object, but it does have static methods.

The Scala translation of singleton objects uses a combination of static and instance methods. For every Scala singleton object, the compiler will create a Java class for the object with a dollar sign added to the end.
For a singleton object named App, the compiler produces a Java class named App$.
This class has all the methods and fields of the Scala singleton object.
The Java class also has a single static field named MODULE$ to hold the one instance of the class that is created at run time.
As a full example, suppose you compile the following singleton object:

object App {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}

Scala will generate a Java App$ class with the following fields and methods:

$ javap App$
public final class App$ extends java.lang.Object
    implements scala.ScalaObject{
  public static final App$ MODULE$;
  public static {};
  public App$();
  public void main(java.lang.String[]);
  public int $tag();
}

That’s the translation for the general case.


You're basically correct.

If you have the singleton

object Singleton {
  def method = "Method result"
}

then compilation gives you

Singleton.class
Singleton$.class

and for the bytecode you find, first for Singleton:

public final class Singleton extends java.lang.Object{
public static final java.lang.String method();
  Signature: ()Ljava/lang/String;
  Code:
   0:   getstatic   #11; //Field Singleton$.MODULE$:LSingleton$;
   3:   invokevirtual   #13; //Method Singleton$.method:()Ljava/lang/String;
   6:   areturn
}

that is, a public static method for each method of the class that references something called Singleton$.MODULE$, and in Singleton$:

public final class Singleton$ extends java.lang.Object implements scala.ScalaObject{
public static final Singleton$ MODULE$;
  Signature: LSingleton$;

public static {};
  Signature: ()V
  Code:
   0:   new #9; //class Singleton$
   3:   invokespecial   #12; //Method "<init>":()V
   6:   return


public java.lang.String method();
  Signature: ()Ljava/lang/String;
  Code:
   0:   ldc #16; //String Method result
   2:   areturn


private Singleton$();
  Signature: ()V
  Code:
   0:   aload_0
   1:   invokespecial   #20; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   putstatic   #22; //Field MODULE$:LSingleton$;
   8:   return
}

Where you see that MODULE$ is what holds the instance of Singleton$, and method is just an ordinary method.

So, that's all there really is to it: create Singleton$ with a static field called MODULE$ to hold the unique instance of itself, populate that field, and then create a Singleton with static methods that forward all static calls to the appropriate methods from Singleton$.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号