我找到了关于如何使用惰性 val将覆盖的成员值传播到超类构造函数的解释。不幸的是,这篇文章没有解释为什么会这样。
我知道非惰性值不能被分配两次,因此,超级构造函数中没有可用的值,因为必须跳过超级类构造函数中的值分配才能不将变量锁定为另一个值。但是,在超级构造函数中执行的println语句,即在分配新的惰性值之前,如何知道这个新值?我对执行顺序感到困惑吗?还是println仅在构造对象后才评估其参数?
我找到了关于如何使用惰性 val将覆盖的成员值传播到超类构造函数的解释。不幸的是,这篇文章没有解释为什么会这样。
我知道非惰性值不能被分配两次,因此,超级构造函数中没有可用的值,因为必须跳过超级类构造函数中的值分配才能不将变量锁定为另一个值。但是,在超级构造函数中执行的println语句,即在分配新的惰性值之前,如何知道这个新值?我对执行顺序感到困惑吗?还是println仅在构造对象后才评估其参数?
这很简单。您只需要注意所有字段和惰性字段都是 getter 方法。
val
getter 返回private[this]
字段的值。private[this]
字段赋值位于主构造函数中:
class Test {
val field = 1
}
意思是这样的:
class Test {
private[this] val _field: Int = _
def field = _field
{ // constructor
_field = 1
}
}
所以在构造函数field
返回默认值之前。
lazy val
使用双重检查锁评估代码块,然后返回结果:
class Test {
lazy val field = 1
}
意思是这样的:
class Test {
private[this] val _field: Int = _
@volatile private[this] val _flag: Boolean = _
def field = {
if (! _flag) {
synchronized {
if (! _flag) {
_field = 1 // code block
_flag = true
}
}
}
_field
}
}
所以lazy val
与构造函数无关,在构造函数之前和之后你会得到相同的结果。
您可以使用scalac -Xprint:mixin test.scala
.