2013-05-04 8 views
5

私は検索しましたが、私の問題の解決策を見つけることができませんでした。私のシナリオは非常に単純です:base.Method()複数の継承レベルが呼び出されていない?

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

私がやろうとしていますどのようなことは、クラスCのインスタンスを持っている(我々はそれに名前を付けましょう「instanceC」)オーバーライドされた親の方法、及びその祖父母の両方を呼び出します。

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

をしかし、その代わりに、これを取得しています:だから私はこれを期待するクラスBの方法で

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

がスキップされています。これは不可能ですか?私はこれが相続/多型の全体のポイントだと思った。前もって感謝します!

+6

CはAからではなくBから派生したものですか? – jure

+0

CがなぜBから来るのですか?あなたはそれがAから継承したいと思う。 – Derek

+10

あなたの例は私のために期待どおりに動作し、 'ABC'を印刷する – Lee

答えて

10

あなたの例は私の期待どおりに機能します。私はA B Cを参照してください。私はあなたの最も可能性の高い問題は、CがBを拡張しないということだと思います。しかし、私たちが主題にいる間は間違いなくより安全なパターンを提案しましょう。あなたは、基本クラスからコードを実行するために、MethodOneのすべてのオーバーライドを望んでいるようです。偉大な、継承は、このための良いパターンです。ただし、このパターンでは、継承者にbase.MethodOne()を呼び出させることができないため、継承者にベースロジックを強制的に実行させることはできません。彼らはbase.MethodOne()を呼び出しても、ロジックの順序を保証することはできません。メソッドの開始時、メソッドの途中、またはメソッドの終了時にbase.MethodOne()と呼びますか?しばしば、これらのタイプのパターンでは、サブクラスが関数の初めにすべてのベースロジックを実行するようにします。次のパターンは、基本クラスが期待する順序で継承者にベースロジックを実行させます。継承者は、基本クラスが指定する方法で基本クラスを拡張する必要があるため、技術的に柔軟性は低くなりますが安全性は高くなります。

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

これは、基本メソッドが常に呼び出されるようにする方法をはっきりと示しているので、他のメソッドよりも優れた答えです。それがなぜ落とされたのか分かりません。 – Andy

+0

私は少しの睡眠で走っており、皆さんは正しいです。 CはCの代わりに愚かにAを拡張していました。それは実際に問題でしたが、実際にはこれがより良い解決策であると思っており、良い結果を得ています。ありがとうございました! – helios

+0

私はdownvotingではなかった、私はそれも私よりも良かったと思って+1を与えた –

1

投稿した例は完全に動作します。実際のコードで行っていることは投稿した内容とは異なります。

Here is your code running on ideoneあなたが望むとおりに機能します。

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"); 
    } 
} 
関連する問題