Scala 初始化顺序对象与 val

问题描述 投票:0回答:1

在下面的程序中,一个对象被报告为 null,即使它已明确初始化。

class MyClass()
class MyOtherClass(c: MyClass)
object Foo {
  val myClass = new MyClass()
  object otherClass extends MyOtherClass(myClass)
  val otherClasses = Seq(otherClass)
}

object Main {
  def main(args: Array[String]): Unit = {
      println(Foo.otherClass)
      println(Foo.otherClasses)
  }
}

打印:

Foo$otherClass$@5410511c
List(null)

现在我通过制作

otherClasses
lazy
解决了这个问题。也可以通过将参数从
MyOtherClass
更改为
null
来解决,但这对我来说不是一个选择。

我总是假设 scala 中对象和类的初始化顺序是从上到下的。显然我的假设是错误的。看起来 vals 首先被初始化。这是边缘情况还是错误?我认为 scala 2 和 3(在 scastie 中都是 3.3.3. 和 3.4.2)中的行为是相同的。

scala object initialization lazy-initialization scala-3
1个回答
0
投票

object
会延迟初始化多年。在 Scala 2.13 规范中,我们读到:

对象定义定义了符合以下条件的单个对象(或:模块) 到模板 tt。大致相当于以下 惰性值的定义:

lazy val mm = new scsc with mt1mt1​ with …… with mtnmtn​ { this: m.typem.type => statsstats }

注意对象定义定义的值是实例化的 懒洋洋。新的 mm$cls 构造函数的计算不是在 对象定义,但在第一次 mm 时进行评估 在程序执行期间取消引用(可能永远不会在 全部)。在评估期间再次尝试取消引用 mm 构造函数将导致无限循环或运行时错误。其他 正在评估构造函数时尝试取消引用 mm 的线程会阻塞,直到评估完成。

Scala 3 没有改变这种行为(尽管 Scala 3 还没有发布它的规范,所以我无法根据规范设置它,但当它发布时我确信这将是预期的行为)。

如果您知道

object otherClass
是惰性值,那么
null
就非常有意义。初始化的顺序是从上到下,但只初始化急切的值,并且
lazy val
(和
object
)是当你必须格外小心并且不要在构造函数中评估它们时。

© www.soinside.com 2019 - 2024. All rights reserved.