2013-05-04 4 views
5

Ich habe gesucht und nicht in der Lage gewesen, eine Lösung für mein Problem zu finden. Mein Szenario ist sehr einfach:base.Method() mit mehreren Vererbungsebenen, die nicht aufgerufen werden?

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"); 
    } 
} 

Was ich versuche, eine Instanz der Klasse C zu tun ist, haben (wir nennen es ‚instanceC‘) rufen sowohl die überschriebene Methode der Mutter, und seine Großeltern. Also würde ich dies erwarten:

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

Aber anstatt dies bin immer:

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

mit der Methode der Klasse B übersprungen werden. Ist das nicht möglich? Ich dachte, das ist der ganze Punkt der Vererbung/Polymorphie. Danke im Voraus!

+6

Sind Sie sicher, dass C von B abgeleitet ist und A nicht? – jure

+0

Warum würde C ovveride von B? Sie wollen es von A. – Derek

+10

Ihr Beispiel als für mich und Drucke ‚ABC‘ – Lee

Antwort

10

Ihr Beispiel funktioniert wie erwartet für mich. Ich sehe A B C. Ich denke, Ihr wahrscheinlichstes Problem ist, dass C B nicht verlängert. Lassen Sie mich jedoch ein wohl sichereres Muster vorschlagen, während wir zu dem Thema sind. Sie scheinen alle Methoden von MethodOne zum Ausführen von Code aus ihren Basisklassen verwenden zu wollen. Großartig, Vererbung ist ein gutes Muster dafür. Mit diesem Muster können Sie jedoch keine Erben erzwingen, die Basislogik auszuführen, da Sie sie nicht zwingen können, base.MethodOne() aufzurufen. Selbst wenn sie base.MethodOne() aufrufen, können Sie die Reihenfolge der Logik nicht sicherstellen. Werden sie base.MethodOne() zu Beginn der Methode, Mitte der Methode oder Ende der Methode aufrufen? Bei diesen Mustertypen möchten Sie oft, dass Unterklassen die gesamte Basislogik zu Beginn der Funktion ausführen. Das folgende Muster erzwingt, dass die Basislogik in der Reihenfolge der Basisklassen erwartet wird. Es ist technisch weniger flexibel, aber sicherer, da Vererber die Basisklassen auf eine Weise erweitern müssen, die die Basisklassen angeben.

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

Dies ist eine bessere Antwort als die andere, da es deutlich zeigt, wie sichergestellt wird, dass die Basismethoden immer aufgerufen werden. Keine Ahnung, warum es abgelehnt wurde. – Andy

+0

Ich renne nur wenig und du hattest Recht; C hat dummerweise A anstatt C verlängert. Obwohl das tatsächlich das Problem war, glaube ich tatsächlich, dass dies eine bessere Lösung ist und gute Ergebnisse bringt. Vielen Dank! – helios

+0

war nicht ich Downvoting, dachte ich, es besser als meine war zu und gab ihm einen +1 –

1

Das Beispiel Sie funktioniert perfekt geschrieben, was auch immer Sie in Ihrer aktuellen Code tun, ist anders als das, was Sie auf dem Laufenden.

Here is your code running on ideone arbeiten so genau wie Sie wollten.

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"); 
    } 
}