2010-06-25 10 views
24

Ho una classe che estende una classe che ho bisogno di sovrascrivere, ma ho bisogno di chiamare la classe genitrice di quella classe. dal momento che non posso chiamare super visto che eseguirà il genitore diretto qual è il modo migliore per ottenere il genitore della mia classe genitore?Java: come si accede a due livelli di un metodo della classe genitore?

Sono sicuro che questa è una domanda di base, ma è da un po 'che non faccio java.

class A 
{ 
public void myMethod() 
{ /* ... */ } 
} 

class B extends A 
{ 
public void myMethod() 
{ /* Another code */ } 
} 

class C extends B 
{ 
I need to call Class A here 
{ /* Another code */ } 
} 
+1

Quasi sempre utilizzando Super è cattiva forma. l'unica probabile eccezione a questo è un metodo overiding che chiama ciò che ha scavalcato. In questi casi potrebbe essere meglio introdurre un metodo astratto o non fare nulla e scavalcare quello con il metodo "originale" reso definitivo. Ciò significa tuttavia che ottieni solo uno scatto. Le gerarchie profonde sono comunque cattive ... –

+0

Possibile duplicato di [Java Come chiamare il metodo dei nonni?] (Http://stackoverflow.com/questions/2584377/java-how-to-call-method-of-grand- i genitori). Relativo anche a http://stackoverflow.com/questions/586363/why-is-super-super-method-not-allowed-in-java – finnw

risposta

27

non lo fai: esso viola l'incapsulamento.

Va bene dire "No, non voglio il mio comportamento - voglio il comportamento dei miei genitori" perché si presume che lo farai solo quando manterrà il tuo stato correttamente.

Tuttavia, non è possibile ignorare il comportamento dei propri genitori - ciò impedirebbe di imporre la propria coerenza. Se la classe genitrice vuole che consenta di chiamare direttamente il metodo grandparent, può esporlo tramite un metodo separato ... ma questo dipende dalla classe genitore.

+0

Grazie, ho capito. Credo che probabilmente mi sto avvicinando a questo nel modo sbagliato. –

9

È possibile non perché è stato sostituito da B. Non v'è alcuna istanza di A all'interno C.

La cosa è che si desidera chiamare un metodo della classe A, ma da cui esempio? Hai istanziato C, che è una classe con un paio di metodi propri e ereditati da B. Se B sta sovrascrivendo un metodo di A, non puoi accedervi da C, perché il metodo stesso appartiene a C (non è un metodo di B, è stato ereditato e ora è in C)

possibili soluzioni:

B non sovrascrive myMethod()

C riceve un'istanza di a e lo salva come una proprietà di classe.

myMethod() in A è statica e si utilizza A.myMethod() (io non lo consiglio)

+0

Grazie, vedo che sto sbagliando, ma grazie per la tua spiegazione. Mi sta aiutando a capire. –

1

Oltre a quanto pakore risposto, si potrebbe anche concatenare super.myMethod() chiamate se funziona per voi. Tu chiamerai myMethod() da A dal myMethod() in B.

class A { 
    public void myMethod() { 
    .... 
    } 
} 

class B extends A { 
    public void myMethod() { 
    .... 
    super.myMethod(); 
    .... 
    } 
} 

class C extends B { 
    public void myMethod() { 
    .... 
    super.myMethod(); //calls B who calls A 
    .... 
    } 
} 

alla fine sarete chiamando myMethod da A, ma indirettamente ... Se funziona per voi.

+0

Funzionerà solo se si desidera che B.myMethod() esegua esattamente la stessa cosa di A.myMethod(), che porta alla seguente domanda: perché diavolo l'hai sovrascritto la prima volta? :) – pakore

+0

@pakore: scusa ... per semplicità di un esempio. Si chiama super.myMethod quando è necessario, in base ad alcune condizioni, flag ecc. Ho modificato un po 'l'esempio per renderlo più chiaro. –

+0

Sì, supponevo che intendessi ciò che hai aggiornato ora. Tieni presente che la tua soluzione non è la stessa che chiama A.myMethod() da C, perché, B.myMethod() sta facendo altre cose che forse C non vuole che siano fatte. C vuole solo A.myMethod() cose da fare, non che AND un altro paio. Ecco perché ho detto che funziona solo se A.myMethod() === B.myMethod(), e quando lo fa, ignorare non ha senso :). – pakore

0

Non è possibile chiamare direttamente il metodo di A. Nei pochi casi che ho riscontrato, la soluzione era aggiungere un metodo in A per esporre la sua implementazione. Per esempio.

class A 
{ 
    public myMethod() { 
     doAMyMethod(); 
    } 

    void doAMyMethod() { 
     // what A want's on doMyMethod, but now it's available 
     // as a separately identifiable method 
    } 
} 

class C extends B 
{ 
    public void someStuff() { 
     this.doAMyMethod(); 
    } 
} 

Il regime separa l'interfaccia pubblica (doMyMethod) dall'attuazione (doAMyMethod). L'ereditarietà dipende dai dettagli dell'implementazione, e quindi non è rigorosamente così grave, ma proverei ad evitarlo se possibile poiché crea uno stretto accoppiamento tra l'implementazione in A e C.

6

Quello che stai chiedendo è male Pratica, Quello che stai dicendo è che C non è un B, ma un A. Quello che devi fare è avere C ereditato da A. Quindi puoi chiamare super.

Se questo non è l'unico modo ...

public String A() 
{ 
String s = "hello"; 
return s; 
} 

public String B() 
{ 
String str = super.A(); 
return str; 
} 

public String C() 
{ 
String s = super.B(); 
return s; 
} 
+1

Grazie, vedo che lo sto facendo nel modo sbagliato e devo pensare a una soluzione migliore. Probabilmente non devo accedere a quel metodo dei nonni per fare quello che voglio. –

0

Quello che faccio per questo caso è:

rendere l'oggetto di classe A all'interno della Classe C e accedere alla classe A lì. Questo esempio che chiarisce ulteriori dettagli:

class A{ 
int a; 
} 
class B extends A{ 
int a; 
} 
class C extends B{ 
int a; 
A obj = new A(); 
public void setData(int p,int q, int r) { 

this.a = p; // points to it's own class 
super.a = q;// points to one up level class i.e in this case class B 
obj.a = r; // obj points the class A 
} 
public void getData() { 
    System.out.println("A class a: "+ obj.a); 
    System.out.println("B class a: "+ super.a); 
    System.out.println("C class a: "+this.a); 
} 
} 

public class MultiLevelInheritanceSuper { 

public static void main(String args[]){ 
    C2 obj = new C2(); 
    obj.setData(10, 20, 30); 
    obj.getData(); 

} 

}

L'output di questo esempio è:

A class a: 30 
B class a: 20 
C class a: 10 
Problemi correlati