PRA*_*NGH 17 polymorphism overriding initialization class kotlin
我创建了以下类层次结构:
open class A {
init {
f()
}
open fun f() {
println("In A f")
}
}
class B : A() {
var x: Int = 33
init {
println("x: " + x)
}
override fun f() {
x = 1
println("x in f: "+ x)
}
init {
println("x2: " + x)
}
}
fun main() {
println("Hello World!!")
val b = B()
println("in main x : " + b.x)
}
Run Code Online (Sandbox Code Playgroud)
这段代码的输出是
open class A {
init {
f()
}
open fun f() {
println("In A f")
}
}
class B : A() {
var x: Int = 33
init {
println("x: " + x)
}
override fun f() {
x = 1
println("x in f: "+ x)
}
init {
println("x2: " + x)
}
}
fun main() {
println("Hello World!!")
val b = B()
println("in main x : " + b.x)
}
Run Code Online (Sandbox Code Playgroud)
但是如果我改变了x
from的初始化
var x: Int = 33
Run Code Online (Sandbox Code Playgroud)
到
var x: Int = 0
Run Code Online (Sandbox Code Playgroud)
与上面的输出相比,输出显示了该方法的调用:
Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么初始化 with0
会导致与另一个值不同的行为?
Sxt*_*nna 19
超类在子类之前初始化。
B的构造函数调用调用A的构造函数,调用函数f打印“x in f:1”,A初始化后,B的其余部分也被初始化。
所以本质上,该值的设置正在被覆盖。
(当你在 Kotlin 中用它们的零值初始化基元时,它们在技术上根本不初始化)
您可以通过更改签名来观察这种“覆盖”行为
var x: Int = 0
到 var x: Int? = 0
由于x
不再是原语int
,该字段实际上被初始化为一个值,产生输出:
Hello World!!
x in f: 1
x: 0
x2: 0
in main x : 0
Run Code Online (Sandbox Code Playgroud)
文档中描述了此行为 - https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order
如果在基类初始化逻辑中使用了这些属性中的任何一个(直接或间接,通过另一个覆盖的开放成员实现),则可能会导致不正确的行为或运行时失败。因此,在设计基类时,应避免在构造函数、属性初始值设定项和 init 块中使用开放成员。
更新:
有一个错误会导致这种不一致 - https://youtrack.jetbrains.com/issue/KT-15642
当一个属性被分配为超级构造函数内的虚函数调用的副作用时,如果初始化表达式是类型默认值(空,原始零),它的初始化器不会覆盖该属性。
归档时间: |
|
查看次数: |
1775 次 |
最近记录: |