J'ai créé la hiérarchie de classes suivante:
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)
}
La sortie de ce code est
Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33
Mais si je change l'initialisation à x
partir
var x: Int = 33
à
var x: Int = 0
la sortie montre l'invocation de la méthode contrairement à la sortie ci-dessus:
Hello World!!
x in f: 1
x: 1
x2: 1
in main x : 1
Est-ce que quelqu'un sait pourquoi l'initialisation avec 0
provoque un comportement différent de celui avec une autre valeur?
class
kotlin
initialization
polymorphism
overriding
PRATYUSH SINGH
la source
la source
Réponses:
la super classe est initialisée avant la sous-classe.
L'appel du constructeur de B appelle le constructeur de A, qui appelle la fonction f en imprimant "x dans f: 1", après que A est initialisé, le reste de B est initialisé.
Donc, essentiellement, le réglage de la valeur est écrasé.
(Lorsque vous initialisez des primitives avec leur valeur nulle dans Kotlin, elles ne se initialisent techniquement pas du tout)
Vous pouvez observer ce comportement de "remplacement" en modifiant la signature de
var x: Int = 0
àvar x: Int? = 0
Depuis
x
n'est plus le primitifint
, le champ est réellement initialisé à une valeur, produisant la sortie:la source
Ce comportement est décrit dans la documentation - https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order
UPD:
Il y a un bogue qui produit cette incohérence - https://youtrack.jetbrains.com/issue/KT-15642
la source
f()
dans leinit
bloc deA
donne l'avertissement "Appel de la fonction non finale f dans le constructeur"var x: Int = 0
) de la classe dérivée n'est pas exécutée du tout, ce qui est contraire à ce que dit la documentation, ce qui m'amène à penser que cela pourrait être un bogue.