繁体   English   中英

Scala中lazy vals的范围规则是什么?

[英]What are the scope rules for lazy vals in Scala?

我正在阅读sbt文档,我在多项目构建一节中遇到了这个例子:

import sbt._
import Keys._

object HelloBuild extends Build {
    lazy val root = Project(id = "hello",
                            base = file(".")) aggregate(foo, bar)

    lazy val foo = Project(id = "hello-foo",
                           base = file("foo"))

    lazy val bar = Project(id = "hello-bar",
                           base = file("bar"))
}

我想知道如何在声明值之前引用值foo和bar? 我认为这与lazy关键字有关,但从我的阅读中,我认为lazy关键字只会延迟初始化? 看来这里的值甚至在声明之前都在某种程度上,从不介意初始化......

希望有人能够解释这里发生了什么!

请参阅Scala语言规范的第4章:

声明或定义引入的名称范围是包含绑定的整个语句序列。 但是,对块中的前向引用存在限制:在构成块的语句序列s 1 ... s n中 ,如果s i中的简单名称是指由s j定义的实体,其中j≥i,则为s i和s j之间的所有s k

  • s k不能是变量定义。
  • 如果s k是值定义,则它必须是惰性的。

换句话说:你可以在lazy vals上有前向引用,但前提是它们之间没有vars或非惰性val。 如果你认为lazy val更像是一个方法而不是变量,那么这很直观,并且在REPL上通过两个快速示例:

scala> object o { val a = b; lazy val c = 6; lazy val b = c }
defined module o

scala> o.a
res1: Int = 6

在第一个示例中,Scala通过调用b计算ab又调用c ,其计算结果为6 但是在下一个例子中,当c不是懒惰的时候......

scala> object o { val a = b; val c = 6; lazy val b = c }
defined module o

scala> o.a
res2: Int = 0

当Scala计算a ,它调用b ,它返回c的当前值(当时为0 ,JVM是整数的默认值,因为c尚未初始化)。 然后 c被初始化,但到那时为时已晚。

另请参见: 如何在Scala 2.10中实现惰性val类变量?

就像在Java中一样,类实例变量(或scala val)在包含类/对象的任何部分内都是“在范围内”,而不管它在何处被声明。

也就是说,对于任何引用它并在声明之前运行的代码,它不会被“初始化”。 lazy-val的代码不会在声明它的位置运行,所以这是安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM