2010-09-19 6 views
41

Ich habe eine Basisklasse und eine Klasse erben Basis. Die Basisklasse verfügt über mehrere virtuelle Funktionen, die von der geerbten Klasse überschrieben werden können. Die virtuellen Funktionen in der Basisklasse verfügen jedoch über Code, der ausgeführt werden muss, bevor die geerbten Klassenüberschreibungen aufgerufen werden. Gibt es eine Möglichkeit, dass ich die virtuellen Funktionen der Basisklassen zuerst aufrufen kann, dann die geerbten Klassenüberschreibungen. Ohne einen Aufruf von base.function().Call-Base-Funktion dann geerbte Funktion

Ich weiß, ich kann einfach zwei Funktionen machen, eine, die aufgerufen wird, die andere virtuelle. Aber gibt es eine Möglichkeit, dass ich dieselben Namen behalten kann? Ich weiß, dass ich einige Dinge ändern muss.

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

ähnliche Frage here.

Antwort

44

Eine gängige Lösung im .NET Framework ist das Aufteilen einer Methode in eine öffentliche Methode XXX und eine geschützte, virtuelle Methode OnXXX, die von der public-Methode aufgerufen wird. Für Ihr Beispiel würde es so aussehen:

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

    protected virtual void OnMyMethod() 
    { 
    } 
} 

und

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

Gibt es eine Möglichkeit, dies zu tun, ohne zwei Funktionen in der Basisklasse zu machen?oder zumindest den gleichen Namen haben? – Dave

+3

@Dave: Nein, es gibt keine Möglichkeit, eine überschriebene Basismethode vor oder nach dem virtuellen Methodenaufruf magisch aufzurufen. Sie müssen es in irgendeiner Weise teilen. (Wenn Sie es teilen, können Sie auch erzwingen, dass eine überschreibende Methode die überschriebene Basismethode aufruft, zusätzlich zu etwas vor und nach der geschützten Methode.) – dtb

+3

Dies wird auch als nicht-virtuelles Interface idiom - http: // de. wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface – sll

60

C# keine Unterstützung für diese automatisch erzwingen, aber Sie es mithilfe des template method pattern erzwingen kann. Zum Beispiel stellen Sie sich diesen Code hatte:

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

Das Problem hier ist, dass jede Klasse von Animal Bedürfnisse vererben base.Speak(); nennen das Basisverhalten sicherzustellen ausgeführt wird. Sie können dies automatisch erzwingen, indem Sie den folgenden (etwas andere) Ansatz:

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

In diesem Fall Kunden nur noch die polymorphe Speak Methode sehen, aber das Animal.Speak Verhalten garantiert auszuführen. Das Problem ist, dass wenn Sie weitere Vererbung haben (z. B. class Dachshund : Dog), Sie eine weitere abstrakte Methode erstellen müssen, wenn Sie sicherstellen möchten, dass Dog.Speak ausgeführt wird.

0

Es gibt keine Möglichkeit zu tun, was Sie suchen, außer den 2 Möglichkeiten, die Sie bereits benannt haben.

Entweder Sie machen 2 Funktionen in der Basisklasse, eine, die aufgerufen wird und die andere virtuelle.

Oder Sie rufen base.functionName in der Unterklasse.

0

Nicht genau. Aber ich habe etwas ähnliches mit abstrakten Methoden gemacht.

Abstrakte Methoden müssen von abgeleiteten Klassen überschrieben werden. Abstrakte Prozeduren sind virtuell, sodass Sie sicher sein können, dass die abgeleitete Klassenversion aufgerufen wird, wenn die Basisklasse sie aufruft. Lassen Sie dann den "Must Run Code" Ihrer Basisklasse nach der Ausführung den abstrakten Prozess aufrufen. voila, der Code der Basisklasse wird immer zuerst ausgeführt (vergewissere dich, dass die Basisklasse proc nicht mehr virtuell ist), gefolgt vom Code deiner abgeleiteten Klasse.

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

Warum ist die abstrakte Methode öffentlich? – Casey

0

Was halten Sie davon?

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

    } 
} 
Verwandte Themen