I got the following code snippet referring an example in Chapter 6 of "Programming Scala":
object HelloWorld {
def main(args: Array[String]) {
trait AbstractT2 {
println("In AbstractT开发者_如何学Go2:")
val value: Int
val inverse = 1.0 / value // ???
println("AbstractT2: value = " + value + ", inverse = " + inverse)
}
val c2b = new AbstractT2 {
println("In c2b:") //---->line 1
val value = 10 //---->line 2
}
println("c2b.value = " + c2b.value + ", inverse = " + c2b.inverse)
}
}
The result of the above code is:
In AbstractT2:
AbstractT2: value = 0, inverse = Infinity
In c2b:
c2b.value = 10, inverse = Infinity
Since the anonymous class initialization is after the trait initialization, the result is understandable. But if I exchange line 1 and line 2 in the above example, so that val value = 10
precedes println("In c2b:")
, the result will be:
In AbstractT2:
AbstractT2: value = 10, inverse = 0.1
In c2b:
c2b.value = 10, inverse = 0.1
It seems this time the initialization is successful although it's wrong from language point of view. I can't understand why. Can anybody help on this? Thanks a lot.
Initialization semantics changed from 2.7 to 2.8. Here's the commit, way back in 2008. "HARD HATS ON!"
https://lampsvn.epfl.ch/trac/scala/changeset/16745
Up to 2.7 Scala moved value initializations in front of the superclass constructor
until an initialization which references this
was encountered. There it would stop.
Much, much earlier, this behavior was necessary to get some composition patterns working. Later, we introduced early definitions to get the same patterns working in a more robust way.
But since the behavior was difficult to change it took us until 2.8 to actually do it.
精彩评论