2012-03-28 5 views
6

Aquí está el código, he definido dos clases padre llamado y el Hijo, y crearlos en la función principal:¿Cuál es el orden de los constructores en este código Java?

public class Test { 
    public static void main(String[] args) { 
     Father father = new Son(); 
    } 
} 

class Father { 
    private String name = "father"; 
    public Father() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is father"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

class Son extends Father { 
    private String name = "son"; 
    public Son() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is son"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

y me dio la salida como esta:

this is son 
this is father 
this is son 
this is son 

, pero no puedo entiendo cómo sucedió esto? ¿Alguien puede decirme por qué?

+5

Lección para aprender: No llame a los métodos de los constructores que se pueden anular. – Thilo

+2

Otra lección que debe aprenderse es que siempre debe tratar de encontrar mensajes de "depuración" que no puedan malinterpretarse: cambiaría sus métodos a algo así como 'System.out.println (" Son.who() "); ',' System.out.println ("Son.tell (" + name + ")"); ',' System.out.println ("Father.who()"); 'y' System.out. println ("Padre.tel (" + nombre + ")"); ' –

Respuesta

9
  1. Vamos a empezar con el constructor de Son.

    public Son() { 
        super(); // implied 
        who(); 
        tell(name); 
    } 
    
  2. Se llama padre del constructor.

    public Father() { 
        who(); 
        tell(name); 
    } 
    
  3. Debido who() queda anulado por Son, la versión Son 's se llamará, impresión "este es el hijo".

  4. tell() también se anula pero el valor pasado es Father.name, imprimiendo "this is father".

  5. Por último, los who() y tell(name) llamadas dentro del constructor Son 's se harán impresión 'este es el hijo' y 'esto es el hijo', respectivamente.

3

Cuando crea la instancia Son, se llama al constructor de la clase padre (es decir, Father()); aquí el método who() es llamado, pero es la versión sustituida declarado en el Son, así que aquí tiene su primera línea (donde la cadena está codificada dentro del método).

La segunda línea viene del interior tell(name)Father(), donde se anulados tell() pero name == "father" como la llamada viene de dentro constructor Father 's, y name es un campo de clase Fatherprivate.

El control vuelve al constructor Son(), y las últimas dos líneas provienen directamente del constructor de clase Son.

2

Father() se llama antes de Son(). El constructor predeterminado de las superclases se llama implícitamente, no necesitamos una declaración super() aquí.

Y who() dentro del constructor de Father() llama al método de anulación.

5

Aquí es lo que se llama:

new Son() 
=> 
    Son._init 
    => first every constructor calls super() 
     Father._init 
     Object._init 
     who() => is overridden, so prints "son" 
     tell(name) => name is private, so cannot be overridden => "father" 
    who() => "son" 
    tell(name) => "son" 

lecciones que aprender:

  • campos privados y métodos son privadas. No puede ser anulado
  • No llame a los métodos de constructores que se pueden sustituir. Esto puede llamar a métodos en estado de clase semiautomatizado (sin embargo, esto no sucede en su caso).
0

El código anterior es particular Bad Style (TM). ;-)

Lo que sucede es: No hay instancia de Padre, solo una instancia de Son. (Sin embargo, es una tarea compatible con Father.)

El constructor Son llama al constructor Father. Este último llama a los métodos anulados (!), Por lo tanto, Padre.¡quién y Padre.te nunca son llamados! Los Métodos anulados se invocan antes (!) El constructor Son finalizó.

Mis recomendaciones:

  1. Si se llama a un método en un constructor, que sea final. O haz que toda la clase sea final. O haga que el método llamado sea privado al menos.
  2. Nunca anule un método llamado en un constructor.
  3. Si tiene que infringir las recomendaciones anteriores, escriba extensos comentarios sobre por qué lo hizo y qué espera que suceda. Escriba una prueba unitaria para asegurarse de que sus suposiciones sean válidas.
Cuestiones relacionadas