2009-07-17 17 views
7

Ho questa situazione che, quando AbstractMethod metodo viene richiamato dal ImplementClass voglio far rispettare che MustBeCalled metodo nella AbstractClass viene richiamato. Non ho mai incontrato prima questa situazione. Grazie!Come applicare una chiamata al metodo (nella classe base) quando viene richiamato il metodo di sovrascrittura?

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

In che modo quando AbstractClass.AbstractMethod viene richiamato dalla classe figlio viene generato un evento per richiamare AbstractClass.MustBeCalled. Ma ancora non sei ancora sicuro di come farlo. – Jeff

risposta

8

Un'opzione sarebbe quella di avere la classe astratta fare la chiamata in questo modo. Altrimenti, non c è modo in C# per richiedere a una classe ereditata di implementare un metodo in un certo modo.

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? 
    } 
} 

In questo modo si crea il metodo fronte pubblico desiderato nella classe astratta, dando la classe astratta su come e in che ordine le cose sono chiamati, pur consentendo la classe concreta per fornire funzionalità necessaria.

+0

*** Grazie. *** – Jeff

+0

Ho usato anche questo schema. Credo che questo sia in realtà uno dei modelli di design di Gang Of Four, ma non ho il mio libro qui per confermarlo. – MedicineMan

+0

Che ne dici di aumentare l'evento quando viene chiamato Base.AbstractMethod()? – Jeff

-1

Perché non si può semplicemente chiamare il metodo in AbstractMethod() della classe Implement?

6

Come su

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 questa implementazione, non penso che tu abbia obbligato l'utente a chiamare MustBeCalled. Quando viene chiamato AbstractClass.AbstractMethod, viene chiamato ImplementClass.AbstractMethod, ma MustBeCalled non lo è. Credo che yshuditelu abbia la soluzione migliore – MedicineMan

0

Una cosa le soluzioni precedenti ignorano è che ImplementClass può ridefinire MethodToBeCalled e non chiamare MustBeCalled -

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

Se solo C# consentiti metodi non sovrascritto da sigillare - come parola chiave finale di Java!

L'unico modo che posso pensare di superare questo è utilizzare la delega piuttosto che l'ereditarietà, perché le classi possono essere definite come sigillate. E sto usando uno spazio dei nomi e il modificatore di accesso "interno" per evitare di fornire una nuova implementazione sull'implementazione delle classi. Inoltre, il metodo di override deve essere definito come protetto, altrimenti gli utenti possono chiamarlo direttamente.

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

Il fatto che una classe derivata possa ombreggiare MethodToBeCalled non costituirà un problema per il codice che utilizza l'oggetto della classe derivata come uno di classe base. Penso che le gerarchie dei metodi potrebbero essere migliorate se fossero consentiti metodi "sovrascrivibili"; Non so se ci sia un motivo tecnico che non potrebbero essere. Un metodo overridable privato può essere chiamato solo dalla classe base o dall'override di una classe derivata dello stesso metodo. Sarebbe quindi impossibile chiamare il codice nell'implementazione di base eccetto che all'interno di una chiamata di classe base alla versione più derivata. – supercat

Problemi correlati