加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 转发参考 – 为什么这段代码编译?

发布时间:2020-12-16 09:40:43 所属栏目:安全 来源:网络整理
导读:考虑这个代码段: object A { val b = c val c = "foo" } println( A.b ) // prints "null" 作为更大程序的一部分,这将导致运行时失败。编译器显然允许从’b’到(未初始化)’c’的正向引用,但是’b’留下c的原始空值。为什么这是允许的?有没有从这个功能
考虑这个代码段:

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)

你期望发生什么?构造函数执行的语义保证了两件事情:

>可预测性您可能会在第一时间看到它非直观,但是规则是清楚的,相对容易遵循。>子类可以依赖于已经自己初始化的超类(因此,它的方法可用)。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读