web-dev-qa-db-fra.com

Fonction de base d'appel puis fonction héritée

J'ai une classe de base et une classe héritant de la base. La classe de base possède plusieurs fonctions virtuelles que la classe héritée peut remplacer. Cependant, les fonctions virtuelles de la classe de base ont du code qui DOIT être exécuté avant que les remplacements de classe hérités soient appelés. Existe-t-il un moyen d'appeler les fonctions virtuelles des classes de base d'abord, puis les substitutions de classe héritées. Sans faire appel à base.function ().

Je sais que je peux simplement créer deux fonctions, l'une qui est appelée, l'autre virtuelle. Mais existe-t-il un moyen de conserver les mêmes noms également? Je sais que je devrai peut-être changer certaines choses.

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(); */ }
}

Question similaire ici .

46
Dave

Une solution courante qui peut être trouvée dans le .NET Framework consiste à diviser une méthode en une méthode publique XXX et une méthode virtuelle protégée OnXXX qui est appelée par la méthode publique. Pour votre exemple, cela ressemblerait à ceci:

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

    protected virtual void OnMyMethod()
    {
    }
}

et

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

C # ne prend pas en charge l'application automatique de cela, mais vous pouvez l'appliquer en utilisant modèle de méthode de modèle . Par exemple, imaginez que vous aviez ce code:

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

Le problème ici est que toute classe héritant de Animal doit appeler base.Speak(); pour s'assurer que le comportement de base est exécuté. Vous pouvez appliquer automatiquement cela en adoptant l'approche (légèrement différente) suivante:

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

Dans ce cas, les clients ne voient toujours que la méthode polymorphe Speak, mais l'exécution du comportement Animal.Speak Est garantie. Le problème est que si vous avez un héritage supplémentaire (par exemple class Dachshund : Dog), Vous devez créer une autre méthode abstraite si vous voulez que Dog.Speak Soit garanti pour s'exécuter.

67
Chris Schmich
 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");
    }
}
2
kfir yahalom

Il n'y a aucun moyen de faire ce que vous cherchez autre que les 2 façons que vous avez déjà nommées.

Soit vous créez 2 fonctions dans la classe de base, une qui est appelée et l'autre virtuelle.

Ou vous appelez base.functionName dans la sous-classe.

0
Steve Michelotti

Pas exactement. Mais j'ai fait quelque chose de similaire en utilisant des méthodes abstraites.

Les méthodes abstraites doivent être remplacées par des classes dérivées. Les procs abstraits sont virtuels, vous pouvez donc être sûr que lorsque la classe de base les appelle, la version de la classe dérivée est appelée. Demandez ensuite au "Must Run Code" de votre classe de base d'appeler le processus abstrait après l'exécution. voila, le code de votre classe de base s'exécute toujours en premier (assurez-vous que le proc de la classe de base n'est plus virtuel) suivi du code de votre classe dérivée.

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
Zippit

Que pensez-vous de cela?

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
Jaap