压倒成员和懒惰的val

时间:2013-08-04 20:06:14

标签: scala constructor lazy-evaluation

我找到this explanation关于如何使用 lazy val 将覆盖成员值传播到超类构造函数。不幸的是,这篇文章没有解释为什么会这样。

我理解,非惰性值不能分配两次,因此,超级构造函数中没有值可用,因为超类构造函数中的值赋值必须被滑动以便不将变量锁定到另一个值。但是, println 语句 - 在超级构造函数中执行,即在新的延迟值被赋值之前 - 如何才能知道这个新值?我是否对执行顺序感到困惑?或 println 以某种方式仅在构造对象后评估其参数?

1 个答案:

答案 0 :(得分:6)

这很简单。您应该注意所有字段和惰性字段都是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检查此内容。