Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala初始化顺序_Scala - Fatal编程技术网

Scala初始化顺序

Scala初始化顺序,scala,Scala,在Scala编程(第10章“组合与继承”)一书中,有一个例子引起了一些误解。这是提取的部分: abstract class Element { def contents: Array[String] val someProperty: String = { println("=== Element") contents(0) } } class UniformElement( str: String ) extends Element { val s = s

在Scala编程(第10章“组合与继承”)一书中,有一个例子引起了一些误解。这是提取的部分:

abstract class Element {
  def contents: Array[String]
  val someProperty: String = {
    println("=== Element")
    contents(0)
  }
}

class UniformElement(
  str: String
) extends Element {
  val s = str
  println("=== UniformElement.s " + s)
  def contents = Array(s) // error
  //def contents = Array(str) // ok
}
val e = new UniformElement("str")
println(e.someProperty)
由于某些原因,超类的初始化发生在
s
初始化之前:

scala example.scala
=== Element
=== UniformElement.s str
null

为什么没有
s
(请参见代码中的注释行)替代方法可以工作?

问题是,在构造函数完成之前,字段值为
null
,并且超级构造函数间接引用由子构造函数初始化的值
s
,但子构造函数尚未完成。情况是这样的

class UniformElement {
  def <init>(str: String) = {
    super.<init>()
    s = str
  }
}
它以前执行过

s = str
通常可以通过将渴望的
val s
更改为懒惰的方式来解决问题

class UniformElement(str: String) extends Element {
  lazy val s = str
  println("=== UniformElement.s " + s)

  def contents = Array(s)
}
现在输出什么

=== Element
=== UniformElement.s str
str

谢谢你提出这个有趣的问题!我的猜测(在花了一些时间在Scastie上之后)是以下初始化顺序:

  • 参数:在您的情况下,
    str
    是第一个要定义的值
  • 父项:在您的情况下,
    元素
  • 孩子:在您的情况下,
    制服元素
  • 所以,如果我试着把它放在一个类的顺序中,它是这样的:

    类统一元素{
    //参数初始化
    val str=“str”
    //超级构造函数
    定义内容:数组[字符串]
    val someProperty:字符串={
    println(“==元素”)
    目录(0)
    }
    //子构造函数
    val s=str
    println(“==UniformElement.s”+s)
    def contents=数组//错误
    //def contents=Array(str)//确定
    }
    
    诀窍在于,要初始化
    someProperty
    ,scala需要计算
    contents(0)
    并找到
    contents
    定义。但在查找定义时,
    s
    尚未定义(而
    str
    是)

    因此,最终的“运行时”过程:

    类统一元素{
    //参数初始化
    val str=“str”
    //用定义替换内容的超级构造函数
    val someProperty:字符串={
    println(“==元素”)
    数组(0)//错误:s不存在!
    //数组(str)(0)//确定:str存在
    }
    //子构造函数
    val s=str
    println(“==UniformElement.s”+s)
    def contents=数组//错误
    //def contents=Array(str)//确定
    }
    
    要说服自己,您可以尝试:

    println(e.someProperty)//null=>s未定义
    println(e.contents(0))//str=>s现在已定义
    
    如果需要,请随时要求澄清

    === Element
    === UniformElement.s str
    str