Я создал следующую иерархию классов:
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)
}
Выход этого кода
Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33
Но если я изменю инициализацию x
с
var x: Int = 33
в
var x: Int = 0
результат показывает вызов метода в отличие от вывода выше:
Hello World!!
x in f: 1
x: 1
x2: 1
in main x : 1
Кто-нибудь знает, почему инициализация с 0
вызывает другое поведение, чем с другим значением?
class
kotlin
initialization
polymorphism
overriding
ПРАТЮШ СИНГХ
источник
источник
Ответы:
Суперкласс инициализируется перед подклассом.
Вызов конструктора B вызывает конструктор A, который вызывает функцию f, печатающую "x in f: 1", после инициализации A инициализируется остальная часть B.
По сути, установка значения перезаписывается.
(Когда вы инициализируете примитивы с их нулевым значением в Kotlin, они технически просто не инициализируются вообще)
Вы можете наблюдать это «перезаписать» поведение, изменив подпись с
var x: Int = 0
вvar x: Int? = 0
Поскольку
x
больше не является примитивомint
, поле фактически инициализируется значением, что приводит к выводу:источник
Это поведение описано в документации - https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order.
UPD:
Существует ошибка, которая вызывает это несоответствие - https://youtrack.jetbrains.com/issue/KT-15642
источник
f()
вinit
блокеA
выдает предупреждение «Вызов не финальной функции f в конструкторе»var x: Int = 0
) производного класса вообще не выполняется, что противоречит тому, что написано в документации, что приводит меня к мысли, что это может быть ошибкой.