为什么在 Scala 中重写的变量会得到错误的值?

2023-12-21

我在 Scala 中有一个 A 类,就像这样:

class A {
  val a = 3
  lazy val b = 2
  println("a = " + a)
  println("b = " + b)
}

接下来,我将这个类扩展到另一个 B 类:

class B extends A {
  override val a = 4
  override lazy val b = 3
}

现在,当我创建一个对象时class B,我得到以下输出:

a = 0  //the default value of int is zero `0` in Scala
b = 3

而我期望的输出是:

a = 3
b = 2

我的问题是如何println()功能于class A了解中定义的值class B,但仅限于b而不是a?


docs.scala-lang.org - 教程 - 初始化顺序 https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html提供了完整的解释。


为了看得更清楚,我们在课堂上打印同样的东西B就像在课堂上一样A:

class A {
  val a = 3
  lazy val b = 2
  println("A: a = " + a)
  println("A: b = " + b)
}

class B extends A {
  override val a = 4
  override lazy val b = 3
  println("B: a = " + a)
  println("B: b = " + b)
}

在这种情况下,new B()产生:

A: a = 0
A: b = 3
B: a = 4
B: b = 3

非惰性的初始化顺序val变量由下式给出:

在缺乏“早期定义”(见下文)的情况下,初始化 strict vals 按以下顺序完成。

  1. 超类在子类之前完全初始化。
  2. 否则,按声明顺序。

Thus A之前已完全初始化B.

But val不能多次初始化。所以 Scala 内部给它一个默认值(0 for an Int, null for a String, ..) 当首先处理超类时A.

因此它打印0一开始(初始化时A) 进而4(初始化时B).


使用lazy vals是提出的解决方案scaladoc https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html来绕过这个限制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在 Scala 中重写的变量会得到错误的值? 的相关文章

随机推荐