Вызовите базовую функцию, затем унаследованную функцию - PullRequest
46 голосов
/ 20 сентября 2010

У меня есть базовый класс и класс, наследующий базу. Базовый класс имеет несколько виртуальных функций, которые унаследованный класс может переопределять. Однако виртуальные функции в базовом классе имеют код, который ДОЛЖЕН запускаться до вызова переопределенных наследуемых классов. Есть ли способ, которым я могу вызывать виртуальные функции базовых классов сначала, а затем наследуемый класс переопределяет. Без вызова 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(); */ }
}

Подобный вопрос здесь .

Ответы [ 6 ]

67 голосов
/ 20 сентября 2010

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

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.

50 голосов
/ 20 сентября 2010

Распространенным решением, которое можно найти в .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 голосов
/ 07 апреля 2018
 public abstract class BaseTemp
{
    public void printBase() {
        Console.WriteLine("base");
        print();
    }

    public abstract void print();

}

public class TempA: BaseTemp
{
    public override void print()
    {
        Console.WriteLine("TempA");
    }
}

public class TempB: BaseTemp
{
    public override void print()
    {
        Console.WriteLine("TempB");
    }
}
0 голосов
/ 20 сентября 2010

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

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()
    { 

    }
}
0 голосов
/ 20 сентября 2010

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

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

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

        // call derived object's code
        myDerivedMustcallFunction();    
    }

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

class myInherited : myBase
{
    public override myDerivedMustCallFunction()
    { /* code to be run in derived class here */ }
}
0 голосов
/ 20 сентября 2010

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

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

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

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