2009-06-23 14 views
33

qui sta lavorando il codice JavaIl metodo sovrascritto del genitore può chiamare java in altri oggetti ma non in un sottotipo?

class Cup { 
    public String sayColor() { 
     return "i have a color ."; 
    } 
} 

class TCup extends Cup{ 
    public String sayColor(){ 
     System.out.println(super.getClass().getName()); 
     return super.sayColor()+"color is tee green."; 
    } 
} 

class MyTCup extends TCup { 
    public String sayColor(){ 
     System.out.println(super.getClass().getName()); 
     return super.sayColor()+"but brushed to red now!"; 
    } 
} 
class Test { 
    public static void main(String[] args) { 
     Cup c = new MyTCup(); 
     System.out.print(c.sayColor()); 
    } 
} 

e in esecuzione le stampe classe di test

MyTCup 
MyTCup 
i have a color .color is tee green.but brushed to red now! 

domanda 1: Alla fase di esecuzione, l'oggetto di tipo di C è MyTCup, ma sempre possibile chiamare il metodo eccellente . C'è uno stack di metodi nella memoria in MyTCup dopo l'inizializzazione dell'oggetto, e quindi può richiamare in fase di runtime come il codice?

domanda 2: domanda: Non c'è modo di chiamare il metodo super in altri oggetti. Come so, C++ può eseguire il cast per chiamare il metodo genitore in qualsiasi momento. Perché il design java come questo?

+1

Probabilmente dovresti accettare la risposta una volta che sei soddisfatto :) –

risposta

65

Non è possibile chiamare il metodo super in altri oggetti, che violerebbe l'incapsulamento. L'intero punto è che l'oggetto controlla quali sono i suoi metodi sovrascritti. Ad esempio, potresti sovrascrivere il metodo add di una raccolta per generare un'eccezione in determinate circostanze, in modo da garantire che solo gli elementi "validi" siano stati aggiunti alla raccolta. Sarebbe inutile se i chiamanti potessero semplicemente bypassarlo con un cast!

L'unico motivo per cui un oggetto può chiamare super.foo() per se stesso consiste nell'abilitare che una chiamata venga implementata utilizzando l'implementazione principale. È compito del codice della classe assicurarsi che lo faccia sempre in modo sensato. Ancora una volta, per prendere l'esempio del componente aggiuntivo, se la raccolta ha la precedenza su add, è necessario che sia del tipo di aggiungere l'elemento convalidato alla raccolta, cosa che farebbe con super.add().

Si noti che per lo stesso motivo di encapuslation, si può solo chiamare l'implementazione genitore, non l'implementazione nonni - in modo super.foo() è valido, ma non è super.super.foo().

+0

Vedi anche http: // stackoverflow.com/questions/586363/why-is-super-super-method-not-allowed-in-java (che hai risposto molto bene). –

+0

E guarda che ... Ho usato lo stesso esempio :) –

+0

per la tua risposta molto! Penso che sia il punto. – sting

1

1:

La tua domanda non è chiara. Cosa intendi con "call through in runtime come il codice"? Se ti stai chiedendo in che modo l'istanza c sa qual è la sua super classe, allora sì, la gerarchia delle classi viene memorizzata e può essere letta dalla VM.

2:

Java realmente fa ti permettono di lanciare un'istanza al suo genitore. È solo che chiamare un metodo su un'istanza usa sempre la classe effettiva dell'istanza, non la sua classe di compilazione. Cioè in Java tutti i metodi sono quelli che verrebbero chiamati "virtuali" in C++. Perché questo è stato deciso non lo so.

Modifica: In realtà Jon Skeet spiega molto bene il motivo per cui non è possibile chiamare un metodo di una super classe su un'istanza di una classe secondaria, quindi ora so :-).

+0

Intendo il metodo "sayColor" chiamato da MyTCup a TCup e Cup e la classe visualizzata è "MyTCup". I metodi appartengono a MyTCup o appartengono a TCup, Cup.Non conosco jvm, forse tutti nell'area del metodo. – sting

0

È possibile definire un nuovo metodo di supporto nella sottoclasse in modo da non eseguire l'override dell'originale - chiamarlo - può chiamare il metodo super o meno, a seconda di ciò che si desidera.

0

In realtà è possibile, ma è necessario utilizzare una metodologia, quindi funzionerà solo sul proprio codice.
Al super classe, aggiungere il parametro "Class" per il metodo, come in:

public String sayColor(Class classFilter){... 

ora, ad ogni sostituzione, si controlla per vedere se l'attuale sotto-classe è quella del filtro specificato Mi piace:

if(TCup.class!=classFilter)return super.sayColor(classFilter); 
return "some text for TCup only"; 

Ho codificato in modo esclusivo. Puoi aggiungere più parametri o confrontare con null, in modo da poter unire i risultati con le super classi, usare la tua creatività :)

Problemi correlati