Reputation: 57274
I've been thinking of scala objects as simply shorthand for singleton java objects - that is, I'd expect them to behave like objects with guaranteed singleton instantiation. Then I run into something like this, which I don't understand:
object Test extends App{
var x ="a"
override def main(args:Array[String]):Unit = {
println(x )
}
}
which prints null rather than "a".
Looking at the generated classes, I get a Test$.class which is the object definition; however the instance value "a" is defined in a companion Test class using a generated delayedInit. Can someone shed some light on how this is instantiated? Clearly the mental model I had of this is incorrect.
Upvotes: 3
Views: 1912
Reputation: 4966
Let's first take a look at App
and how it works. The documentation of App reveals the following caveats:
It should be noted that this trait is implemented using the DelayedInit functionality, which means that fields of the object will not have been initialized before the main method has been executed.
It should also be noted that the main method will not normally need to be overridden: the purpose is to turn the whole class body into the “main method”. You should only chose to override it if you know what you are doing.
Ok, great. Now that we know these two facts, let's fix your code. There are two possible solutions we can consider:
Let's only override the main method when we know what we're doing:
object Test extends App{
var x ="a"
println(x )
}
Or we can choose to define a main
method, but not extend App
:
object Test {
var x ="a"
def main(args:Array[String]):Unit = {
println(x )
}
}
You're understanding of objects is correct. What's confusing is the DelayedInit that App
implements. Happy coding ;)
Upvotes: 4