scala – 转发参考 – 为什么这段代码编译?
考虑这个代码段:
object A { val b = c val c = "foo" } println( A.b ) // prints "null" 作为更大程序的一部分,这将导致运行时失败。编译器显然允许从’b’到(未初始化)’c’的正向引用,但是’b’留下c的原始空值。为什么这是允许的?有没有从这个功能中受益的编程场景? 将代码更改为直序,行为更改: val b = c val c = "foo" println( b ) // prints "foo" 为什么行为不一样?为什么这甚至工作?谢谢。 更新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" } } 对于什么是值得的,IDEA也认为(当我点击“通过”在val b = c中引用’c’)我指的是(稍后)的’c’声明。 解决方法
类或对象的主体是主构造函数。一个构造函数,就像一个方法一样,是一系列语句,它们按顺序执行 – 要做任何其它事情,它必须是一个非常不同的语言。我很确定你不希望Scala以任何其他顺序执行方法的语句,而不是顺序执行。
这里的问题是,类和物体的身体也是成员的声明,这是你的混乱的根源。您可以看到val声明正是:声明式的编程形式,如Prolog程序或XML配置文件。但他们真的是两件事: // This is the declarative part object A { val b val c } // This is the constructor part object A { b = c c = "foo" } 你的问题的另一部分是你的例子很简单。这是一种特殊情况,某种行为似乎是有意义的。但要考虑一下: abstract class A { def c: String } class B extends A { val b = c override val c = "foo" } class C extends { override val c = "foobar" } with B val x = new C println(x.b) println(x.c) 你期望发生什么?构造函数执行的语义保证了两件事情: >可预测性您可能会在第一时间看到它非直观,但是规则是清楚的,相对容易遵循。>子类可以依赖于已经自己初始化的超类(因此,它的方法可用)。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |