2009-07-17 4 views
7

Ich habe diese Situation, dass, wenn AbstractMethod Methode von ImplementClass aufgerufen wird Ich will erzwingen, dass MustBeCalled Methode in der Abstract aufgerufen wird. Ich bin noch nie auf diese Situation gestoßen. Vielen Dank!Wie erzwingen Sie einen Methodenaufruf (in der Basisklasse), wenn das Überschreiben der Methode aufgerufen wird?

public abstract class AbstractClass 
{ 
    public abstract void AbstractMethod(); 

    public void MustBeCalled() 
    { 
     //this must be called when AbstractMethod is invoked 
    } 
} 

public class ImplementClass : AbstractClass 
{ 
    public override void AbstractMethod() 
    { 
     //when called, base.MustBeCalled() must be called. 
     //how can i enforce this? 
    } 
} 
+0

Wie wäre es, wenn AbstractClass.AbstractMethod von Kind-Klasse aufgerufen wird ein Ereignis ausgelöst wird AbstractClass.MustBeCalled aufzurufen. Aber immer noch unsicher, wie es geht. – Jeff

Antwort

8

Eine Option zu tun auf diese Weise die Berufung wäre die abstrakte Klasse zu haben. Andernfalls gibt es in C# keine Möglichkeit, eine vererbte Klasse zur Implementierung einer Methode auf eine bestimmte Art zu benötigen.

public abstract class AbstractClass 
{ 
    public void PerformThisFunction() 
    { 
     MustBeCalled(); 
     AbstractMethod(); 
    } 

    public void MustBeCalled() 
    { 
     //this must be called when AbstractMethod is invoked 
    } 

    //could also be public if desired 
    protected abstract void AbstractMethod(); 
} 

public class ImplementClass : AbstractClass 
{ 
    protected override void AbstractMethod() 
    { 
     //when called, base.MustBeCalled() must be called. 
     //how can i enforce this? 
    } 
} 

Dadurch wird die gewünschte öffentlich zugängliche Methode in der abstrakten Klasse erzeugt, über die abstrakte Klasse geben, wie und in welcher Reihenfolge der Dinge genannt werden, während immer noch die konkrete Klasse ermöglicht benötigte Funktionalität bereitzustellen.

+0

*** Vielen Dank. *** – Jeff

+0

Ich habe dieses Muster auch verwendet. Ich glaube, das ist tatsächlich eines der Gang Of Four Designmuster, aber ich habe mein Buch hier nicht, um das zu bestätigen. – MedicineMan

+0

Wie wäre es, ein Ereignis auszulösen, wenn Base.AbstractMethod() aufgerufen wird? – Jeff

-1

Warum können Sie nicht einfach die Methode in der AbstractMethod() der Klasse implementieren aufrufen?

6

Wie wäre es

public abstract class AbstractClass 
{ 
    public void AbstractMethod() 
    { 
     MustBeCalled(); 
     InternalAbstractMethod(); 
    } 

    protected abstract void InternalAbstractMethod(); 

    public void MustBeCalled() 
    { 
     //this must be called when AbstractMethod is invoked 
    } 
} 

public class ImplementClass : AbstractClass 
{ 
    protected override void InternalAbstractMethod() 
    { 
     //when called, base.MustBeCalled() must be called. 
     //how can i enforce this? 
    } 
} 
+1

In dieser Implementierung glaube ich nicht, dass Sie den Benutzer gezwungen haben, MustBeCalled aufzurufen. Wenn AbstractClass.AbstractMethod aufgerufen wird, wird ImplementClass.AbstractMethod aufgerufen, MustBeCalled jedoch nicht. Ich glaube, Yshuditelu hat die bessere Lösung – MedicineMan

0

Eine Sache, die vorangehenden Lösungen zu ignorieren ist, dass ImplementClass MethodToBeCalled neu definieren und MustBeCalled nicht nennen -

public abstract class AbstractClass 
{ 
    public abstract void AbstractMethod(); 

    private void MustBeCalled() 
    { 
     //will be invoked by MethodToBeCalled(); 
     Console.WriteLine("AbstractClass.MustBeCalled"); 
    } 

    public void MethodToBeCalled() 
    { 
     MustBeCalled(); 
     AbstractMethod(); 
    } 
} 

public class ImplementClass : AbstractClass 
{ 
    public override void AbstractMethod() 
    { 
     Console.WriteLine("ImplementClass.InternalAbstractMethod"); 
    } 

    public new void MethodToBeCalled() { 
     AbstractMethod(); 
    } 
} 

Wenn nur C# erlaubt nicht außer Kraft gesetzt Methoden versiegelt werden - wie Java Schlüsselwort final!

Die einzige Möglichkeit, dies zu überwinden, ist die Verwendung der Delegierung statt der Vererbung, da die Klassen als versiegelt definiert werden können. Und ich verwende einen Namespace und den "internen" Zugriffsmodifikator, um zu verhindern, dass eine neue Implementierung für implementierende Klassen bereitgestellt wird. Außerdem muss die Methode zum Überschreiben als geschützt definiert werden, andernfalls können Benutzer sie direkt aufrufen.

namespace Something 
{ 

    public sealed class OuterClass 
    { 
     private AbstractInnerClass inner; 

     public OuterClass(AbstractInnerClass inner) 
     { 
      this.inner = inner; 
     } 

     public void MethodToBeCalled() 
     { 
      MustBeCalled(); 
      inner.CalledByOuter(); 
     } 

     public void MustBeCalled() 
     { 
      //this must be called when AbstractMethod is invoked 
      System.Console.WriteLine("OuterClass.MustBeCalled"); 
     } 
    } 

    public abstract class AbstractInnerClass 
    { 
     internal void CalledByOuter() 
     { 
      AbstractMethod(); 
     } 

     protected abstract void AbstractMethod(); 
    } 
} 

public class ImplementInnerClass : Something.AbstractInnerClass 
{ 
    protected override void AbstractMethod() 
    { 
     //when called, base.MustBeCalled() must be called. 
     //how can i enforce this? 
     System.Console.WriteLine("ImplementInnerClass.AbstractMethod"); 
    } 

    public new void CalledByOuter() 
    { 
     System.Console.WriteLine("doesn't work"); 
    } 
} 
+0

Die Tatsache, dass eine abgeleitete Klasse MethodToBeCalled überschatten kann, stellt kein Problem für Code dar, der das abgeleitete Klassenobjekt als Basisklasse verwendet. Ich denke, dass Methodenhierarchien verbessert werden könnten, wenn "private überschreibbare" Methoden erlaubt wären; Ich weiß nicht, ob es einen technischen Grund gibt, warum sie nicht sein könnten. Eine private überschreibbare Methode konnte nur von der Basisklasse oder von einer abgeleiteten Klassenüberschreibung der gleichen Methode aufgerufen werden. Es wäre daher unmöglich, den Code in der Basisimplementierung aufzurufen, außer innerhalb eines Aufrufs der Basisklasse für die am weitesten abgeleitete Version. – supercat

Verwandte Themen