Reputation: 75
object ObjectExample {
def main(args: Array[String]): Unit = {
val student = new Student("zhu", 18, "zz")
println(student.gender)
}
}
class People(val name: String, val age: Int) {
println("constructor")
println(name)
val gender: String = "male"
println(gender)
def this(name1: String) = { //it is useless in here
this("ci", 18)
println("subconstructor")
println(name)
println(gender)
}
}
class Student(name: String, age: Int, val school: String) extends People(name, age){
println("derived constructor")
println(name)
println(school)
override val gender: String = "female"
println(gender)
}
the first gender
which I think I have already Initialized, But What it print is null. I try to overwrite it in Student
class and it print "female".
here are results, the third line is what People
's gender
output
constructor
zhu
null
derived constructor
zhu
zz
female
female
Upvotes: 1
Views: 621
Reputation: 1435
This is explained in Scala FAQ - Why is my abstract or overriden val null?
Citation from page:
A ‘strict’ or ‘eager’ val is one which is not marked lazy.
In the absence of “early definitions” (see below), initialization of strict vals is done in the following order.
Superclasses are fully initialized before subclasses. Otherwise, in declaration order. Naturally when a val is overridden, it is not initialized more than once. So though x2 in the above example is seemingly defined at every point, this is not the case: an overridden val will appear to be null during the construction of superclasses, as will an abstract val.
There is a compiler flag which can be useful for identifying this situation:
-Xcheckinit: Add runtime check to field accessors.
Page also offers three solutions (see FAQ page for details):
Upvotes: 2
Reputation: 51271
I think section 5.1.4 Overriding of the language spec has the pertinent information.
...the binding of the overriding member ... must subsume the binding of the overridden member...
What's more, I believe the Early Definitions syntax was designed to address this issue.
class Student(name: String, age: Int, val school: String
) extends {override val gender = "female"} with People(name, age) {
println("derived constructor")
println(name)
println(school)
//override val gender: String = "female"
println(gender)
}
Now the output has no null
.
constructor
zhu
female
derived constructor
... (etc.)
Upvotes: 2