multiple - Salida perpleja en Java con métodos de herencia y anulación
herencia multiple en java ejemplos (1)
Hay algunos hechos que debe saber antes de comenzar a explicar cada paso de la ejecución del código:
- Las referencias de campo se resuelven según el tipo de referencia y las llamadas al método se resuelven durante el tiempo de ejecución (de forma dinámica) en función del tipo de objeto.
-
super()
se coloca implícitamente en cada constructor, incluso si no lo pones allí mismo (no se llama si llamas asuper(int x, int y)
por ejemplo). - Se considera una muy mala práctica llamar a los métodos "anulables" de un constructor; verás por qué cuando pasamos por la ejecución.
Ahora desglosemos su código paso a paso:
- Crea una instancia de
B
llamando a su constructor predeterminadoB()
. - Como dije antes, la llamada a
super()
se agrega implícitamente a cualquier constructor, por lo queA()
se llama inmediatamente. - Dentro de
A()
llama afoo()
, que está anulado en la claseB
y es por eso que se llama afoo()
desdeB
- Dentro de
foo()
B
obtienes la salidaB.foo(): bar = null
ya que Java no llegó a inicializar los campos deB
(¡su constructor no se ha ejecutado todavía!) Y los campos de tipo de objeto se inicializan anull
por defecto. - Ahora que hemos terminado con el constructor de
A()
volvemos al constructor deB()
. - Dentro de dicho constructor, tenemos la llamada a
foo()
otra vez, que es otra vezB
''sfoo()
. Pero a diferencia de la última vez,B
tiene sus campos inicializados (después de la llamada asuper()
) correctamente, por lo que obtienes el esperadoB.foo(): bar = B.bar
. - Ahora hemos vuelto al cálido abrazo de
main
. - Usted accede a
a.bar
, y como dije que las referencias de campo se resuelven según el tipo de referencia, obtiene labar
de campo deA
- Por último, por la misma razón, se llama
a.foo()
que de nuevo desencadena elfoo()
B
que imprimeb.bar
una vez más.
Y hemos terminado! :)
Referencias adicionales y materiales de lectura que valen la pena:
Explicación estática y dinámica explicada
Orden de llamadas de constructor
Me encontré con esta pieza de código.
Traté de adivinar cuál será el resultado de ejecutarlo antes de hacerlo realmente. Estaba realmente confundido cuando los vi y necesitaba algunas explicaciones.
Este es el código:
public class A {
String bar = "A.bar";
A() { foo(); }
public void foo() {
System.out.println("A.foo(): bar = " + bar);
}
}
public class B extends A {
String bar = "B.bar";
B() { foo(); }
public void foo() {
System.out.println("B.foo(): bar = " + bar);
}
}
public class C {
public static void main(String[] args) {
A a = new B();
System.out.println("a.bar = " + a.bar);
a.foo();
}
}
El resultado es:
B.foo(): bar = null
B.foo(): bar = B.bar
a.bar = A.bar
B.foo(): bar = B.bar
¿Porqué es eso?
- ¿Cómo es
bar = null
? - ¿Por qué aparece
a.bar = A.bar
incluso? No he instanciadoA
en absoluto. - Y si aparece
A
, ¿por qué es después deB
?