2013-05-04 14 views
5

Ho cercato e non sono stato in grado di trovare alcuna soluzione al mio problema. Il mio scenario è molto semplice:base.Method() con più livelli di ereditarietà che non vengono chiamati?

public class A 
{ 
    public virtual void MethodOne() 
    { 
     Console.log("A"); 
    } 
} 

public class B : A 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.log("B"); 
    } 
} 

public class C : B 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.log("C"); 
    } 
} 

Quello che sto cercando di fare è di avere un'istanza della classe C (noi assegniamo il nome 'instanceC') chiamare sia il metodo override del suo genitore, e il suo nonno. Quindi mi aspetto questo:

instanceC.MethodOne(); 
// Output: 
// "A" 
// "B" 
// "C" 

Ma invece sto ottenendo questo:

instanceC.MethodOne(); 
// Output 
// "A" 
// "C" 

con metodo di classe di B viene saltato sopra. Non è possibile? Ho pensato che questo fosse l'intero punto dell'ereditarietà/polimorfismo. Grazie in anticipo!

+6

Sei sicuro che C sia derivato da B e non A? – jure

+0

Perchè C ovveride da B? vuoi ereditare da A. – Derek

+10

Il tuo esempio funziona come previsto per me e stampa 'ABC' – Lee

risposta

10

Il tuo esempio funziona come previsto per me. Vedo A B C. Penso che il tuo problema più probabile sia che C non estenda B. Tuttavia, lasciatemi suggerire un modello discutibilmente più sicuro mentre siamo sull'argomento. Sembra che vogliate eseguire l'override di MethodOne per eseguire codice dalle loro classi base. Grande, l'eredità è un buon modello per questo. Tuttavia, con questo modello non è possibile forzare gli ereditari ad eseguire la logica di base perché non è possibile forzarli a chiamare base.MethodOne(). Anche se chiamano base.MethodOne(), non è possibile garantire l'ordine della logica. Chiameranno lo base.MethodOne() all'inizio del metodo, al centro del metodo o alla fine del metodo? Spesso, in questi tipi di pattern, si desidera che le sottoclassi eseguano tutta la logica di base all'inizio della funzione. Il seguente schema costringe gli ereditari ad eseguire la logica di base nelle aspettative delle classi di base. È tecnicamente meno flessibile ma più sicuro perché gli eredi devono estendere le classi base in un modo che le classi base specificano.

public class A 
{ 
    //Don't make this method virtual because you don't actually want inheritors 
    //to be able to override this functionality. Instead, you want inheritors 
    //to be able to append to this functionality. 
    public void MethodOne() 
    { 
     Console.WriteLine("A"); 
     MethodToBeOverriddenOne(); 
    } 
    //Expose a place where inheritors can add extra functionality 
    protected virtual void MethodToBeOverriddenOne() { }  
} 

public class B : A 
{ 
    //Seal the method because you don't actually want inheritors 
    //to be able to override this functionality. Instead, you want inheritors 
    //to be able to append to this functionality. 
    protected sealed override void MethodToBeOverriddenOne() 
    { 
     Console.WriteLine("B"); 
     MethodToBeOverriddenTwo(); 
    } 
    //Expose a place where inheritors can add extra functionality 
    protected virtual void MethodToBeOverriddenTwo() { } 
} 

public class C : B 
{ 
    protected sealed override void MethodToBeOverriddenTwo() 
    { 
     Console.WriteLine("C"); 
    } 
} 
+1

Questa è una risposta migliore rispetto all'altra in quanto mostra chiaramente come assicurarsi che i metodi di base vengano sempre chiamati. Non ho idea del motivo per cui è stato downvoted. – Andy

+0

Sto correndo per dormire poco e voi ragazzi avete ragione; C stava estrapolando stupidamente A invece che C. Quindi, mentre quello era davvero il problema, in realtà penso che questa sia una soluzione migliore e sto avendo dei buoni risultati. Grazie! – helios

+0

Non ero io a fare downvoting, pensavo fosse meglio del mio e gli ho dato un +1 –

1

L'esempio che hai pubblicato funziona perfettamente, qualunque cosa tu stia facendo nel tuo codice attuale è diversa da quella che hai pubblicato.

Here is your code running on ideone funziona esattamente come desiderato.

using System; 

public class Test 
{ 
     public static void Main() 
     { 
       var c = new C(); 
       c.MethodOne(); 
     } 
} 

public class A 
{ 
    public virtual void MethodOne() 
    { 
     Console.WriteLine("A"); 
    } 
} 

public class B : A 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.WriteLine("B"); 
    } 
} 

public class C : B 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.WriteLine("C"); 
    } 
}