请考虑以下代码段:
object A {
val b = c
val c = "foo"
}
println( A.b ) // prints "null"
Run Code Online (Sandbox Code Playgroud)
作为更大程序的一部分,这将导致运行时失败.编译器显然允许从'b'到(未初始化)'c'的前向引用,但是'b'留下c的原始空值.为什么允许这样做?是否有可以从此功能中受益的编程方案?
将代码更改为直接序列并且行为更改:
val b = c
val c = "foo"
println( b ) // prints "foo"
Run Code Online (Sandbox Code Playgroud)
为什么行为不同?为什么这甚至有效?谢谢.
更新1:
问题出现了我如何运行第二个例子.我简化了设置并使用最新的Scala插件在IntelliJ IDEA 10.5.2中使用Scala 2.9.0.1编译它.这是确切的代码,在一个新创建的和其他空项目中,我用它来测试它,它在这种环境中编译并运行良好:
package test
object Main {
def main( args: Array[String] ) {
val b = c
val c = "foo"
println( b ) // prints "foo"
}
}
Run Code Online (Sandbox Code Playgroud)
对于它的价值,IDEA还认为(当我点击"通过"对val b = c中的'c'的引用时)我指的是(c)的(后面)声明.
可能重复:
转发引用 - 为什么这段代码会编译?
Scala和前向引用
object Main extends App {
val a = 4
val b = a + c
val c = 5
println(b) // => 4
}
Run Code Online (Sandbox Code Playgroud)
这将打印4作为c显然是0当b被分配.a并且c是价值观,因此它们不应该0在一个时刻,而5在下一个时刻.在Scala中,它们应该是不可变的,对吧?
我不应该至少得到某种警告吗?当然,在上面的例子中,你必须是一个想念它的白痴,但在更复杂的情况下,很难说出它的顺序.
我当然知道我可以使用,lazy val b = ...但如果我认为我把它按正确的顺序排列,当我真的没有时.不是很危险,因为根本没有得到任何警告吗?运行得很好!?这是如何获得通过两者的Scala IDE 和编译器?这是故意的吗?或者这是一个无法修复的错误?:/
:)