Singletons as Synthetic classes in Scala?
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 namedApp
, the compiler produces a Java class namedApp$
.
This class has all the methods and fields of the Scala singleton object.
The Java class also has a single static field namedMODULE$
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$
.
精彩评论