2013-05-04 2 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" 

Но вместо этого я получаю это:

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

с методом класса Б пропуску через. Разве это невозможно? Я думал, что это весь смысл наследования/полиморфизма. Заранее спасибо!

+6

Вы уверены, что C является производным от B, а не A? – jure

+0

Почему C ovveride от 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 глупо расширил A вместо C. Так что, хотя это действительно проблема, я действительно думаю, что это лучшее решение, и у меня хорошие результаты. Спасибо! – helios

+0

Не было ли у меня нигде, я думал, что это лучше, чем у меня, и дал ему +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"); 
    } 
} 
Смежные вопросы