2011-12-09 25 views
8

Nel seguente esempio:Chiamare un metodo sovrascritto da un costruttore

class Base {  
    int x=10; 

    Base() {  
     show(); 
    } 

    void show() { 
     System.out.print ("Base Show " +x + " "); 
    } 
} 

class Child extends Base { 
    int x=20; 

    Child() { 
     show(); 
    } 

    void show() {  
     System.out.print("Child Show " + x +" ") ; 
    } 

    public static void main(String s[ ]) { 
     Base obj = new Child(); 
    } 
} 
  • Perché l'output come mostrato di seguito
Child Show 0 Child Show 20 
  • ho pensato costruttori posso solo accedere ai membri dell'istanza una volta che è il suo super costruttore s hanno completato.

Penso che quello che sta accadendo qui è che il super costruttore sta chiamando il metodo show() del bambino perché questo metodo è stato sovrascritto in Child. come è stato sovrascritto, ma perché è il valore di x 0 e perché è in grado di accedere a questo metodo prima che il super costruttore sia completato?

+0

esprime meccanismo di movimentazione virtuale abilitato durante la costruzione di un oggetto? Dubito che non lo sia. – Mahesh

+0

In C++ questo può causare un arresto anomalo. –

+3

Efficace Java è una grande risorsa Java e ci si occupa in dettaglio. Dall'elemento 17: "*** I costruttori non devono invocare metodi overridable **, direttamente o indirettamente (...) Se il metodo di override dipende da qualsiasi inizializzazione eseguita dal costruttore della sottoclasse, il metodo non si comporterà come previsto. ... * "Se hai il libro a portata di mano consiglio vivamente di leggere questo articolo. –

risposta

11

Penso che quello che sta accadendo qui è che il super costruttore sta chiamando il metodo show() del bambino perché questo metodo è stato sovrascritto in Child.

Questo è corretto

ma perché è il valore di x 0

perché non è inizializzata ancora (x del bambino)

e perché è in grado accedere a questo metodo prima che il super costruttore sia completato?

Questo è esattamente il motivo per cui in un costruttore non si dovrebbe mai chiamare un metodo, che può essere sovrascritto (pubblico non finale e protetto).

Edit:

La cosa strana qui è che ogni cosa ha il difetto di visibilità/package-privato. Questo può avere alcuni effetti strani. Vedere: http://www.cooljeff.co.uk/2009/05/03/the-subtleties-of-overriding-package-private-methods/

Si consiglia di evitare metodi di sovrascrittura con visibilità predefinita se possibile (è possibile impedirlo dichiarandoli definitivi).

+1

+1 La sequenza è main -> Child() -> Base() -> Child.show() [x non ancora inizializzata] -> Base.show() [preceduta da Base.x = 20] – stacker

+0

No, il sequence è main -> Base() -> Child.show() [x non ancora inizializzato] -> Child() [Child.x = 20] -> Child.show() – Puce

+0

fa la variabile x sulla classe Child ha è stato assegnato un valore predefinito di 0 quando la classe Object è stata completata? Perché per quanto posso ricordare qui è la sequenza: new Child() -> Base() -> Object -> Implementazione child di show() ... – anathema

6

È possibile chiamare i metodi sovrascritto da costruttori, ma è male e si non dovrebbe. Hai illustrato il motivo per cui questo non funziona: la classe derivata non ha la possibilità di essere inizializzata, quindi verranno utilizzati i campi non inizializzati: nel tuo esempio, il valore predefinito perx è 0, ecco perché sta stampando 0.

2

concatenamento costruttore ha senso spiegare esattamente che cos'è. Il primo compito del metodo del costruttore di una sottoclasse è chiamare il metodo di costruzione della superclasse.Ciò garantisce che la creazione dell'oggetto della sottoclasse inizi con l'inizializzazione delle classi sopra di essa nella catena di ereditarietà.

http://java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm

http://javahours.blogspot.com/2008/12/constructor-chain.html

Problemi correlati