Scala:使用硬编码值的特征初始化代码
Scala: Trait initialisation code using hard-coded values
以下代码:
trait A{
val s: String = "A"
println(s"A's initialiser run, s= $s")
}
object O1 extends A {
override val s = "O1"
println(s"Object's initialiser run, s= $s")
def foo: Unit = println("I am just being called to instantiate the object! :| ")
}
object O2 extends AnyRef with A {
override val s = "O2"
println(s"Object's initialiser run, s= $s")
def foo: Unit = println("I am just being called to instantiate the object! :| ")
}
println("////with inheritance:")
O1.foo
println("////with mix-in:")
O2.foo
打印:
////with inheritance:
A's initialiser run, s= null
Object's initialiser run, s= O1
I am just being called to instantiate the object! :|
////with mix-in:
A's initialiser run, s= null
Object's initialiser run, s= O2
I am just being called to instantiate the object! :|
我觉得这种行为很奇怪。我会预料到以下行为之一:
"...s = O1"
, "...s = O1"
"...s = A "
、"...s = O1"
但两者都没有发生。
当 s
保留为抽象 val
而不是 def
时,我可以理解类似的行为,但我发现该值被简单地忽略很奇怪。我的问题是:
- 表面下发生了什么导致了这种行为?
- 编译器如何similar/different看到运行具有硬编码值的特征与具有抽象值的特征中的初始化块的情况。
- 为什么 Scala 决定这样做而不是上面详述的两个预期场景。
- 编译器不应该警告我们在 traits 主体中除了值设置之外还有其他内容吗?
这是由于s
被子类、Scala[=35=覆盖造成的] compiler
会将其翻译成 抽象值 ,例如:
public abstract java.lang.String s();
s
将在所有superclass
完成初始化(A
)后初始化,并且只会初始化一次(在O1
或O2
) superclass
完成初始化后,因此当 A
的初始化块尝试打印时 s
将得到 null
.
并且有一个参考很有帮助:
https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
以下代码:
trait A{
val s: String = "A"
println(s"A's initialiser run, s= $s")
}
object O1 extends A {
override val s = "O1"
println(s"Object's initialiser run, s= $s")
def foo: Unit = println("I am just being called to instantiate the object! :| ")
}
object O2 extends AnyRef with A {
override val s = "O2"
println(s"Object's initialiser run, s= $s")
def foo: Unit = println("I am just being called to instantiate the object! :| ")
}
println("////with inheritance:")
O1.foo
println("////with mix-in:")
O2.foo
打印:
////with inheritance:
A's initialiser run, s= null
Object's initialiser run, s= O1
I am just being called to instantiate the object! :|
////with mix-in:
A's initialiser run, s= null
Object's initialiser run, s= O2
I am just being called to instantiate the object! :|
我觉得这种行为很奇怪。我会预料到以下行为之一:
"...s = O1"
,"...s = O1"
"...s = A "
、"...s = O1"
但两者都没有发生。
当 s
保留为抽象 val
而不是 def
时,我可以理解类似的行为,但我发现该值被简单地忽略很奇怪。我的问题是:
- 表面下发生了什么导致了这种行为?
- 编译器如何similar/different看到运行具有硬编码值的特征与具有抽象值的特征中的初始化块的情况。
- 为什么 Scala 决定这样做而不是上面详述的两个预期场景。
- 编译器不应该警告我们在 traits 主体中除了值设置之外还有其他内容吗?
这是由于s
被子类、Scala[=35=覆盖造成的] compiler
会将其翻译成 抽象值 ,例如:
public abstract java.lang.String s();
s
将在所有superclass
完成初始化(A
)后初始化,并且只会初始化一次(在O1
或O2
) superclass
完成初始化后,因此当 A
的初始化块尝试打印时 s
将得到 null
.
并且有一个参考很有帮助:
https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html