2010-08-17 17 views
11

¿Por qué es la última impresión "Soy una clase infantil". ?Herencia de Java

public class Parent 
{ 
    String parentString; 
    public Parent() 
    { 
     System.out.println("Parent Constructor."); 
    } 

    public Parent(String myString) 
    { 
     parentString = myString; 
     System.out.println(parentString); 
    } 

    public void print() 
    { 
     System.out.println("I'm a Parent Class."); 
    } 
} 

public class Child extends Parent 
{ 
    public Child() { 
     super("From Derived"); 
     System.out.println("Child Constructor."); 
    } 

    public void print() 
    { 
     super.print(); 
     System.out.println("I'm a Child Class."); 
    } 

    public static void main(String[] args) 
    { 
     Child child = new Child(); 
     child.print(); 
     ((Parent)child).print(); 
    } 
} 

de salida:

From Derived 

Child Constructor. 

I'm a Parent Class. 

I'm a Child Class. 

I'm a Parent Class. 

I'm a Child Class. 

Respuesta

15

Debido a que este es un ejemplo de polymorphism (finales de unión). En tiempo de compilación, especifica que el objeto es del tipo Parent y, por lo tanto, solo puede llamar a los métodos definidos en Parent. Pero en el tiempo de ejecución, cuando ocurre la "vinculación", se invoca el método en el objeto, que es del tipo Child, sin importar cómo se haga referencia en el código.

La parte que lo sorprende es por qué debe invocarse el método principal durante el tiempo de ejecución. En Java (a diferencia de C# y C++) todos los métodos son virtual y, por lo tanto, se invoca el método de anulación. Consulte this example para comprender la diferencia.

+1

Buena pregunta y buena respuesta. Esto también es bueno en programas reales; su código podría romperse si accidentalmente tuviera algún código que llamara a la implementación principal. – Tormod

2

Ambos:

child.print(); 

y

((Parent)child).print(); 

debe devolver:

I'm a Parent Class. 
I'm a Child Class. 

En ese orden.

La conversión de un objeto a su clase base no cambia qué método se realiza.

En este caso, incluso después del lanzamiento, se llama al método de impresión infantil y no al elemento primario.

+0

Lo que me confundió fue que el mismo código en C# solo imprime "Soy de clase para padres" – vad

+0

La herencia y el polimorfismo funcionan exactamente de la misma manera en C#. Sin embargo, C# requiere la palabra clave virtual para los métodos que desea anular en la herencia de subclases, por lo que supongo que no utilizó virtual, por lo tanto, obtuvo el resultado diferente. – vicsz

0

Aunque el hijo se convierta en primario, esto no cambia la implementación del método. Esto en realidad no lo convierte en un padre. Es por esto que se puede hacer algo como:

Image img = new BufferedImage(...); 

A pesar de que la imagen es abstracta img sigue siendo un BufferedImage debajo.

0

Aunque lo esté lanzando como clase principal, eso no significa que usará las funciones de sus padres: solo tratará el objeto como primario.

Al decir ((Parent) child) .print(); usted está diciendo "Trate este objeto como un Objeto principal, no como un objeto secundario". No "Usar las implementaciones del método principal"

Por lo tanto, si el objeto secundario tuviera otros métodos, no podría llamarlos. Pero dado que print() es un método del padre, aún puede llamarlo, pero usa la implementación real del objeto (no la clase a la que se le asigna).

0

en java si llamamos a cualquier método en un objeto, entonces llama al método usando el sub objeto más ............... aquí:

Objeto | | Padre | | Niño < - sub objeto más

Caso 1 ::

niño Niño = nueva guardería();

child.print(); 

este llamado de impresión Método de la clase hijo usando objeto hijo ... hijo es más sub por lo que imprime

de salida ::

Soy una clase padre. Soy una clase infantil.

Explicación: Desde el método secundario está llamando al método principal debido a super.print(); método así que la primera línea es que soy una clase para padres. después de completar los controles de ejecución del método principal regresa al método secundario e imprime I'm a Child Class.

Caso 2 ::

((Parent)child).print(); 
if we call like this jvm calls print() method by using sub most object here sub most object is child object so it prints 

output:: 
      I'm a Parent Class. 
      I'm a Child Class. 

Explicación: De niño método se llama método de matriz debido super.print(); método así que la primera línea es que soy una clase para padres. después de completar los controles de ejecución del método principal regresa al método secundario e imprime I'm a Child Class.