2010-09-19 7 views
41

J'ai une classe de base et une base héritière de classe. La classe de base a plusieurs fonctions virtuelles que la classe héritée peut remplacer. Cependant, les fonctions virtuelles dans la classe de base ont un code qui DOIT s'exécuter avant que les substitutions de classe héritées ne soient appelées. Est-il possible que je puisse d'abord appeler les fonctions virtuelles des classes de base, puis les remplacements de classe hérités. Sans faire un appel à base.function().Fonction de base d'appel puis fonction héritée

Je sais que je peux simplement faire deux fonctions, l'une qui est appelée, l'autre virtuelle. Mais y a-t-il un moyen de garder les mêmes noms? Je sais que je vais devoir 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(); */ } 
} 

Une question similaire here.

Répondre

44

Une solution commune qui peut être trouvée dans le .NET Framework consiste à fractionner une méthode dans une méthode publique XXX et une méthode virtuelle protégée OnXXX appelée par la méthode publique. Pour exemple, il 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 
    } 
} 
+0

Y at-il un moyen que je peux faire cela sans faire deux fonctions dans la classe de base?ou à tout le moins les faire avoir le même nom? – Dave

+3

@Dave: Non, il n'y a aucun moyen d'appeler magiquement une méthode de base surchargée avant ou après l'appel de la méthode virtuelle. Vous devez le diviser d'une manière ou d'une autre. (Si vous le divisez, vous pouvez également appliquer qu'une méthode de substitution appelle la méthode de base substituée, en plus de faire quelque chose avant et après la méthode protégée.) – dtb

+3

Ceci est également connu sous le nom d'interface idiome non-virtuelle - http: // en. wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface – sll

60

C# ne prend pas en charge de l'application automatiquement, mais vous pouvez l'appliquer à l'aide du template method pattern. 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 est ici que toute classe héritant de Animal doit appeler base.Speak(); pour assurer le comportement de base est exécutée. Vous pouvez automatiquement appliquer en prenant l'approche suivante (légèrement différente):

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 encore que voir la méthode Speak polymorphes, mais le comportement Animal.Speak est garanti à exécuter. Le problème est que si vous avez d'autres héritages (par exemple, class Dachshund : Dog), vous devez créer une autre méthode abstraite si vous voulez que l'exécution de Dog.Speak soit garantie.

0

Il n'y a aucun moyen de faire ce que vous êtes à la recherche autre que les 2 façons déjà nommé.

Soit vous faire 2 fonctions dans la classe de base, qui est appelée et l'autre virtuel.

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

0

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

Les méthodes abstraites doivent être remplacée par les classes dérivées. Les procédures abstraites sont virtuelles, 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. Ensuite, demandez à votre classe de base "Doit exécuter le code" appeler le proc 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 */ } 
} 
+1

Pourquoi la méthode abstraite est-elle publique? – Casey

0

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

    } 
} 
Questions connexes