He creado la siguiente jerarquía de clases:
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 salida de este código es
Hello World!!
x in f: 1
x: 33
x2: 33
in main x : 33
Pero si cambio de la inicialización de x
partir
var x: Int = 33
a
var x: Int = 0
el resultado muestra la invocación del método en contraste con el resultado anterior:
Hello World!!
x in f: 1
x: 1
x2: 1
in main x : 1
¿Alguien sabe por qué la inicialización con 0
causa un comportamiento diferente al de otro valor?
class
kotlin
initialization
polymorphism
overriding
PRATYUSH SINGH
fuente
fuente
Respuestas:
La superclase se inicializa antes de la subclase.
La llamada al constructor de B llama al constructor de A, que llama a la función f imprimiendo "x en f: 1", después de que A se inicializa, el resto de B se inicializa.
Entonces, esencialmente, la configuración del valor se sobrescribe.
(Cuando inicializa primitivas con su valor cero en Kotlin, técnicamente no se inicializan en absoluto)
Puede observar este comportamiento de "sobrescritura" cambiando la firma de
var x: Int = 0
avar x: Int? = 0
Como
x
ya no es la primitivaint
, el campo en realidad se inicializa a un valor, produciendo la salida:fuente
Este comportamiento se describe en la documentación: https://kotlinlang.org/docs/reference/classes.html#derived-class-initialization-order
UPD:
Hay un error que produce esta inconsistencia: https://youtrack.jetbrains.com/issue/KT-15642
fuente
f()
en elinit
bloque deA
da la advertencia "Llamar a la función no final f en el constructor"var x: Int = 0
) de la clase derivada no se ejecuta en absoluto, lo que es contrario a lo que dice la documentación, lo que me lleva a creer que esto podría ser un error.