[英]Scala initialization order
在《 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
初始化發生在s
初始化之前:
scala example.scala
=== Element
=== UniformElement.s str
null
為什么在沒有s
情況下替代方法有效(請參見代碼中的注釋行)?
問題是字段值在構造函數完成之前為null
,並且超級構造函數間接引用由子構造函數初始化的值s
,但子構造函數尚未完成。 情況看起來像這樣
class UniformElement {
def <init>(str: String) = {
super.<init>()
s = str
}
}
在這里可以查看是否將super.<init>()
替換為
val someProperty: String = {
println("=== Element")
contents(0)
}
它執行之前
s = str
初始化順序問題通常可以通過將急切的val s
變為lazy來解決,就像這樣
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
是要定義的第一個值 Element
UniformElement
因此,如果我嘗試將其放在單個類中,則它會像這樣:
class UniformElement{
// Argument init
val str = "str"
// Super constructor
def contents: Array[String]
val someProperty: String = {
println("=== Element")
contents(0)
}
// Child constructor
val s = str
println("=== UniformElement.s " + s)
def contents = Array(s) // error
//def contents = Array(str) // ok
}
訣竅在於,要啟動someProperty
,scala需要評估contents(0)
並找到contents
定義。 但是當找到定義時, s
尚未定義(而str
是)。
最后的“運行時”過程:
class UniformElement{
// Argument init
val str = "str"
// Super constructor with contents replaced by definition
val someProperty: String = {
println("=== Element")
Array(s)(0) // error : s doesn't exists !
// Array(str)(0) // ok : str exists
}
// Child constructor
val s = str
println("=== UniformElement.s " + s)
def contents = Array(s) // error
//def contents = Array(str) // ok
}
為了說服自己,您可以嘗試:
println(e.someProperty) // null => s wasn't defined
println(e.contents(0)) // str => s is now defined
如有需要,請隨時澄清。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.