Подтвердить что ты не робот

Функция базового вызова, затем унаследованная функция

У меня есть базовый класс и класс, наследующий базу. Базовый класс имеет несколько виртуальных функций, которые унаследованный класс может переопределить. Тем не менее, виртуальные функции в базовом классе имеют код, который ДОЛЖЕН запускаться до того, как вызовутся наследуемые переопределения классов. Есть ли способ, с помощью которого я могу сначала вызвать базовые классы виртуальных функций, а затем унаследованный класс переопределяет. Без вызова функции base.function().

Я знаю, что могу просто сделать две функции, одну из которых вызывается, другую виртуальную. Но есть ли способ сохранить те же имена? Я знаю, что мне, возможно, придется кое-что изменить.

class myBase
{
    public virtual myFunction()
        { /* must-run code, Called first */ }
}

class myInherited : myBase
{
    public override myFunction()
        { /* don't use base.myFunction();,
        called from base.myFunction(); */ }
}

Аналогичный вопрос здесь.

4b9b3361

Ответ 1

Общим решением, которое можно найти в .NET Framework, является разделение метода на открытый метод XXX и защищенный виртуальный метод OnXXX, который вызывается общедоступным методом. Для вашего примера это будет выглядеть так:

class MyBase
{
    public void MyMethod()
    {
        // do something
        OnMyMethod();
        // do something
    }

    protected virtual void OnMyMethod()
    {
    }
}

и

class MyInherited : MyBase
{
    protected override void OnMyMethod()
    {
        // do something
    }
}

Ответ 2

У С# нет поддержки для автоматического принудительного выполнения этого, но вы можете применить его, используя шаблон шаблона . Например, представьте, что у вас есть этот код:

abstract class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("I'm an animal.");
    }
}

class Dog : Animal
{
    public override void Speak()
    {
        base.Speak();
        Console.WriteLine("I'm a dog.");
    }
}

Проблема заключается в том, что любой класс, наследующий от Animal, должен вызвать base.Speak();, чтобы гарантировать, что выполняется базовое поведение. Вы можете автоматически принудительно выполнить это, выполнив следующий (немного другой) подход:

abstract class Animal
{
    public void Speak()
    {
        Console.WriteLine("I'm an animal.");
        DoSpeak();
    }

    protected abstract void DoSpeak();
}

class Dog : Animal
{
    protected override void DoSpeak()
    {
        Console.WriteLine("I'm a dog.");
    }
}

В этом случае клиенты все еще видят только полиморфный метод Speak, но поведение Animal.Speak гарантировано выполняется. Проблема в том, что если у вас есть дополнительное наследование (например, class Dachshund : Dog), вам нужно создать еще один абстрактный метод, если вы хотите, чтобы Dog.Speak гарантировался выполнение.

Ответ 3

Нет способа сделать то, что вы ищете, кроме двух способов, которые вы уже назвали.

Либо вы делаете 2 функции в базовом классе, который вызывается, а другой виртуальный.

Или вы вызываете base.functionName в подкласс.

Ответ 4

Не совсем. Но я сделал что-то подобное, используя абстрактные методы.

Абстрактные методы должны быть переопределены производными классами. Абстрактные procs являются виртуальными, поэтому вы можете быть уверены, что когда базовый класс вызывает их, вызывается производная версия класса. Затем ваш базовый класс "Обязательный код выполнения" вызовет абстрактный поток после запуска. voila, ваш код базового класса всегда запускается первым (убедитесь, что базовый класс proc больше не является виртуальным), за которым следует код производного класса.

class myBase
{
    public /* virtual */ myFunction()  // remove virtual as we always want base class function called here 
    { /* must-run code, Called first */ 

        // call derived object code
        myDerivedMustcallFunction();    
    }

    public abstract myDerivedMustCallFunction() { /* abstract functions are blank */ }
}

class myInherited : myBase
{
    public override myDerivedMustCallFunction()
    { /* code to be run in derived class here */ }
}

Ответ 5

Что вы думаете об этом?

class myBase
{
    public void myFunctionWrapper()
    {
        // do stuff that must happen first
        // then call overridden function
        this.myFunction();
    }

    public virtual void  myFunction(){ 
       // default implementation that can be overriden

    }

}

class myInherited : myBase
{
    public override void myFunction()
    { 

    }
}