// Cannot change source code
class Base
{
public virtual void Say()
{
Console.WriteLine("Called from Base.");
}
}
// Cannot change source code
class Derived : Base
{
public override void Say()
{
Console.WriteLine("Called from Derived.");
base.Say();
}
}
class SpecialDerived : Derived
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
class Program
{
static void Main(string[] args)
{
SpecialDerived sd = new SpecialDerived();
sd.Say();
}
}
Результат:
Названный от полученного специального.
Названный от Полученного./* это не ожидается */
Названный от основы.
Как я могу переписать класс SpecialDerived так, чтобы средний класс "Полученный" метод не называли?
ОБНОВЛЕНИЕ: причиной, почему я хочу наследоваться Полученному вместо Основы, является Производный класс, содержит много других реализаций. Так как я не могу сделать base.base.method()
здесь, я предполагаю, что лучший способ состоит в том, чтобы сделать следующее?
//Не может изменить исходный код
class Derived : Base
{
public override void Say()
{
CustomSay();
base.Say();
}
protected virtual void CustomSay()
{
Console.WriteLine("Called from Derived.");
}
}
class SpecialDerived : Derived
{
/*
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
*/
protected override void CustomSay()
{
Console.WriteLine("Called from Special Derived.");
}
}
Вы не можете из C#. Из IL это действительно поддерживается. Вы можете сделать невиртуальный вызов любого из ваших родительских классов... но, пожалуйста, не делайте этого :)
.Это плохая практика программирования, и она недопустима в C#. Это плохая практика программирования, потому что
Детали grandbase - это детали реализации базы; вы не должны полагаться на них. Базовый класс предоставляет абстракцию поверх основной базы; вы должны использовать эту абстракцию, а не строить обходной путь, чтобы избежать ее.
Вы произошли от своего базового класса, потому что вам нравится то, что он делает, и вы хотите повторно использовать и расширить его. Если вам не нравится то, что она делает, и вы хотите обходить ее, а не работать с ней, тогда зачем вы вообще от нее отталкивались? Выводите из grandbase сами, если это та функциональность, которую вы хотите использовать и расширять.
База может требовать определенных инвариантов в целях безопасности или семантической согласованности, которые поддерживаются деталями того, как база использует методы основной базы. Разрешение производному классу базы пропустить код, поддерживающий эти инварианты, может привести базу в непоследовательное, испорченное состояние.
Ответ (я знаю, что это не то, что вы ищете):
class SpecialDerived : Base
{
public override void Say()
{
Console.WriteLine("Called from Special Derived.");
base.Say();
}
}
По правде говоря, у вас есть только прямое взаимодействие с классом вы наследуете от. Думайте об этом классе как о слое, предоставляющем столько или меньше его или его родительских функций, сколько он желает своим производным классам.
РЕДАКТИРОВАТЬ:
Ваше редактирование работает, но я думаю, что я бы использовал что-то вроде этого:
class Derived : Base
{
protected bool _useBaseSay = false;
public override void Say()
{
if(this._useBaseSay)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Конечно, в реальной реализации вы могли бы сделать что-то подобное для расширяемости и ремонтопригодности:
class Derived : Base
{
protected enum Mode
{
Standard,
BaseFunctionality,
Verbose
//etc
}
protected Mode Mode
{
get; set;
}
public override void Say()
{
if(this.Mode == Mode.BaseFunctionality)
base.Say();
else
Console.WriteLine("Called from Derived");
}
}
Затем, производные классы могут соответствующим образом контролировать состояние своих родителей.