Scala和前向引用

jde*_*lop 21 scala compilation reference

可能重复:
Scala:转发引用 - 为什么这段代码会编译?

object Omg {

  class A

  class B(val a: A)

  private val b = new B(a)

  private val a = new A

  def main(args: Array[String]) {
    println(b.a)
  }

}
Run Code Online (Sandbox Code Playgroud)

以下代码打印"null".在java中.由于前向引用无效,类似的构造无法编译.问题是 - 为什么它在Scala中编译得很好?这是设计,在SLS中描述还是仅仅是2.9.1中的错误?

par*_*tic 28

这不是一个bug,而是学习Scala时的一个经典错误.Omg初始化对象时,首先将所有值设置为默认值(null在本例中),然后运行构造函数(即对象主体).

要使其工作,只需lazy在您正在引用的声明前添加关键字(a在本例中为值):

object Omg {

  class A

  class B(val a: A)

  private val b = new B(a)

  private lazy val a = new A

  def main(args: Array[String]) {
    println(b.a)
  }
}
Run Code Online (Sandbox Code Playgroud)

a然后根据需要初始化价值.

这种结构很快(值只对所有应用程序运行时初始化一次)和线程安全.

  • 如果你*知道*你正在以错误的顺序执行语句,那么添加`lazy`就有效.但是如果你认为*你有正确的顺序,你可能不会想到添加"不必要的"`懒惰`.:/ (14认同)

jce*_*ern 7

我理解它的方式,这与Scala类的创建方式有关.在Java中,上面定义的类将内联初始化变量,并且由于a尚未定义,因此无法编译.但是,在Scala中,它在Java中更相当于它(在同一场景中也应该生成null):

class Omg {
  private B b = null;
  private A a = null;

  Omg(){ 
    b = new B(a);
    a = new A();
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,你可以使你的b延迟声明,这将推迟设置值直到它被调用(此时将设置一个).


som*_*ytt 6

如果这是一个问题,请-Xcheckinit在开发期间进行编译并迭代,直到异常消失为止.

规范5.1按顺序执行的模板体语句; 4.0的开头,用于块中的前向引用.

前向引用 - 为什么这段代码会编译?