2013-02-01 17 views
6

Sono molto confuso con Overriding Constructors. Costruttore non può essere ignorato è il risultato quello che ottengo quando ho cercato in Google la mia domanda èOverriding Construct

public class constructorOverridden { 

    public static void main(String args[]) { 
     Sub sub = new Sub(); 
     sub.test(); 
    } 
} 

class Super { 
    Super() { 
     System.out.println("In Super constructor"); 
     test(); 
    } 

    void test() { 
     System.out.println("In Super.test()"); 
    } 
} 

class Sub extends Super { 
    Sub() { 
     System.out.println("In Sub constructor"); 
    } 

    void test() { // overrides test() in Super 
     System.out.println("In Sub.test()"); 
    } 
} 

quando ho eseguito questo ho ottenuto il risultato come

In Super constructor 
In Sub.test() 
In Sub constructor 
In Sub.test() 

pls notano il metodo di prova in sottoclasse viene eseguito. È dimostrato che il costruttore della Superclasse è sovrascritto. Se è corretto?

risposta

19

I costruttori non sono polimorfici - non si sostituiscono . Si creano nuovi costruttori nella sottoclasse e ogni costruttore di sottoclasse deve concatenare (possibilmente indirettamente) a un costruttore di superclasse. Se non si concatena in modo esplicito a un costruttore, viene inserita una chiamata implicita al costruttore della superclasse senza parametri all'inizio del corpo del costruttore della sottoclasse.

Ora in termini di sovrascrittura dei metodi - un oggetto è del suo "tipo finale" fin dall'inizio, incluso quando si esegue un costruttore di superclasse. Pertanto, se si stampa getClass() nel codice costruttore Super, l'output sarà ancora Sub. Il risultato è il metodo sottoposto a override (ad esempio Sub.test), anche se il costruttore Sub non è stato ancora eseguito.

Questo è fondamentalmente una cattiva idea, e si dovrebbe quasi sempre evitare di chiamare i metodi potenzialmente sovrascritti nei costruttori - o documento molto chiaramente che sta andando essere il caso (in modo che il codice sottoclasse è consapevole del fatto che si può' si basano su variabili che sono state inizializzate in modo appropriato, ecc.).

+0

Quindi, quale approccio dovrebbe essere usato quando si evita di "chiamare metodi sovrascritti nei costruttori"? Quello che stavo cercando di realizzare è il flusso di base in un costruttore di super classi che chiama i metodi astratti init(), build() then fill(). In modo che tutte le sottoclassi debbano subire lo stesso flusso! – Akshat

+0

@Akshat: Beh, sembra che rientri nella categoria "documento molto chiaro". Di solito c'è un * qualche * modo di progettare intorno a questo, ma è difficile dare una ricetta generale. –

+0

Se potessi dare un link a quei modi, sarebbe fantastico! – Akshat

3

La prima riga implicita di un costruttore è una chiamata a Super(). Ecco perché ottieni quei risultati.

3

Questo è corretto. Quando si crea un'istanza di una sottoclasse, viene chiamato prima il costruttore della superclasse e quindi ogni costruttore successivo nella gerarchia.

Nell'esempio sopra riportato, il costruttore della superclasse richiama un metodo sottoposto a override (test()). Questo funziona, ma è potenzialmente pericoloso poiché il costruttore della sottoclasse non è stato chiamato e la sottoclasse non sarà stata completamente inizializzata. Per questo motivo non è buona pratica chiamare metodi sovrascritti (o sovrascrivibili) in un costruttore.

2

non è un override del costruttore di super-classe e il costruttore non può essere sovrascritto può essere sovraccaricato.

Quando si crea un oggetto classe figlio, la classe super verrà istanziata per prima, quindi verrà eseguita l'istanza della sottoclasse. È come Bambino non può esistere senza genitore.

Il compilatore chiamerà automaticamente il costruttore super-classe dal costruttore sottocategoria.

Sub() { 
    super(); 
    System.out.println("In Sub constructor"); 
} 
4

Non è possibile sovrascrivere il costruttore in quanto il costruttore viene richiamato dal nome della classe che costruisce. Come puoi creare classi diverse con lo stesso costruttore? Inoltre, una classe figlio non eredita i costruttori dal suo genitore.

Se il costruttore genitore fa un po 'di inizializzazione importante, può essere chiamato dal costruttore figlio utilizzando super: costruttore di classe

class Err extends Throwable { 
    Err(String message) { 
     super(message); // Call the constructor of Throwable. 
     .. 

il genitore è anche sempre chiamato. Se tu stesso non chiami nessuno, un costruttore senza parametri viene chiamato automaticamente prima di entrare in un costruttore della classe derivata. Se il genitore non ha un costruttore senza parametri e non lo si chiama, viene segnalato un errore di compilazione.