Scala Per-Instance Singletons
I was reading about Lift and came across a funky scala syntax:
class Foo {
object bar {
val name = "bob"
}
}
This:
- Declares a
Foo.bar
field - Declares a
bar
inner class - Adds a
Foo.bar()
method that lazy-instantiates a single instance of thebar
inner class for eachFoo
instance
Looking at the decompiled code, it makes more sense:
import java.rmi.RemoteException;
import scala.ScalaObject;
public class Foo implements ScalaObject {
private bar. bar$module;
public Foo() {
}
public final bar. bar() {
class bar. implements ScalaObject {
private final String name = "bob";
public bar.() {
super();
}
public String name() {
return name;
}
public int $tag() throws RemoteException {
return scala.ScalaObject.class.$tag(this);
}
}
if(bar$module == null)
bar$module = new bar.();
return bar$module;
}
public int $tag() throws RemoteException {
return scala.ScalaObject.class.$tag(this);
}
}
My one curiosity is the lack of synchronization in the lazy initialization. I don’t know about the official Scala docs, but Lift insinuated an “inner object” declaration was a singleton, not a singleton-unless-you-have-lots-of-threads.
If you use top-level object
declarations, it seems to make more sense:
object Bar {
def zaz() = {
println("hi")
}
}
As this is decompiled to:
public final class Bar {
public static final void zaz() {
Bar..MODULE$.zaz();
}
public static final int $tag() throws RemoteException {
return Bar..MODULE$.$tag();
}
}
public final class Bar$ implements ScalaObject {
public static final Bar$ MODULE$;
static {
new Bar$();
}
public Bar$() {
MODULE$ = this;
}
public void zaz() {
Predef..MODULE$.println("hi");
}
public int $tag() throws RemoteException {
return ScalaObject.class.$tag(this);
}
}
This uses the Bar$
static initializer to ensure there is just one instance of Bar$
. Which works great.
“Inner” object declarations not being true singletons is probably not a big deal, it was just something I was curious about.