Как назвать base.base.method ()?

// 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.");
    }
}
108
задан Sipo 6 December 2017 в 17:14
поделиться

3 ответа

Вы не можете из C#. Из IL это действительно поддерживается. Вы можете сделать невиртуальный вызов любого из ваших родительских классов... но, пожалуйста, не делайте этого :)

.
23
ответ дан 24 November 2019 в 03:30
поделиться

Это плохая практика программирования, и она недопустима в C#. Это плохая практика программирования, потому что

  • Детали grandbase - это детали реализации базы; вы не должны полагаться на них. Базовый класс предоставляет абстракцию поверх основной базы; вы должны использовать эту абстракцию, а не строить обходной путь, чтобы избежать ее.

  • Вы произошли от своего базового класса, потому что вам нравится то, что он делает, и вы хотите повторно использовать и расширить его. Если вам не нравится то, что она делает, и вы хотите обходить ее, а не работать с ней, тогда зачем вы вообще от нее отталкивались? Выводите из grandbase сами, если это та функциональность, которую вы хотите использовать и расширять.

  • База может требовать определенных инвариантов в целях безопасности или семантической согласованности, которые поддерживаются деталями того, как база использует методы основной базы. Разрешение производному классу базы пропустить код, поддерживающий эти инварианты, может привести базу в непоследовательное, испорченное состояние.

89
ответ дан 24 November 2019 в 03:30
поделиться

Ответ (я знаю, что это не то, что вы ищете):

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

Затем, производные классы могут соответствующим образом контролировать состояние своих родителей.

10
ответ дан 24 November 2019 в 03:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: