Utworzyłem następującą hierarchię klas:
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)
}
Dane wyjściowe tego kodu to
Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33
Ale jeśli zmienię inicjalizację x
z
var x: Int = 33
do
var x: Int = 0
dane wyjściowe pokazują wywołanie metody w przeciwieństwie do danych wyjściowych powyżej:
Hello World!!
x in f: 1
x: 1
x2: 1
in main x : 1
Czy ktoś wie, dlaczego inicjalizacja za pomocą 0
powoduje inne zachowanie niż ta o innej wartości?
class
kotlin
initialization
polymorphism
overriding
PRATYUSH SINGH
źródło
źródło
Odpowiedzi:
superklasa jest inicjowana przed podklasą.
Wywołanie konstruktora B wywołuje konstruktor A, który wywołuje funkcję f wypisującą „x in f: 1”, po zainicjowaniu A reszta B jest inicjalizowana.
Zasadniczo ustawienie wartości jest zastępowane.
(Gdy inicjujesz prymitywy z ich zerową wartością w Kotlinie, technicznie po prostu wcale się nie inicjują)
Możesz zaobserwować to zachowanie „nadpisujące”, zmieniając podpis z
var x: Int = 0
dovar x: Int? = 0
Ponieważ
x
nie jest już prymitywneint
, pole faktycznie zostaje zainicjowane na wartość, co daje wynik:źródło
To zachowanie jest opisane w dokumentacji - https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order
UPD:
Istnieje błąd, który powoduje tę niespójność - https://youtrack.jetbrains.com/issue/KT-15642
źródło
f()
winit
blokuA
ostrzeżenia „Wywoływanie funkcji niefunkcyjnej f w konstruktorze”var x: Int = 0
) klasy pochodnej nie jest wcale uruchamiana, co jest sprzeczne z tym, co mówi dokumentacja, co prowadzi mnie do przekonania, że może to być błąd.