2009-08-25 10 views
5

Avoir quelque chose comme ceci:Comment implémenter une classe de base avec une méthode et forcer la classe dérivée à la remplacer?

public abstract class AAA 
{ 
    protected abstract virtual string ToString() // Error 
    { 
    // Base Stuff 
    } 
} 

public abstract class BBB : AAA 
{ 
    public override string ToString() 
    { 
    // Use base.ToString(); 
    // More Stuff 
    } 
} 

Je lis une autre sorcière après (abstract method in a virtual class) était assez comme ma question, mais il y a une petite différence. Je voudrais AAA.ToString() pour avoir un comportement de base et forcer la classe dérivée pour le remplacer. Je sais que je pourrais faire quelque chose comme ça (défiler vers le bas) mais je cherchais un moyen approprié.

public abstract class AAA 
{ 
    public abstract string ToString(); 
    protected string ToString2() 
    { 
    // Base Stuff 
    } 
} 

public class BBB : AAA 
{ 
    public override string ToString() 
    { 
    // Use base.ToString2(); 
    // More Stuff 
    } 
} 

Je pourrais aussi faire probablement une interface IAAA et construire ma classe BBB comme

public class BBB : AAA, IAAA { ... } 

mais ne regardez pas juste pour moi.

Répondre

5

Votre approche est essentiellement la bonne façon ...

Edit:

Votre "spécification" est:

  1. Comportement par défaut
  2. remplacement requis

Maintenant, depuis que vous app oreille de vouloir le « comportement par défaut » à exécuter toujours, vous avez besoin

public string ToString() 
{ 
    // placeholder for some default behaviour 

    string result = doToString(); 

    // placeholder for some more default behaviour 

    return result; 
} 

protected abstract string doToString(); 

Cela ne fonctionne que si vous savez ce que la classe de base fait en général, et que vous voulez assurer la mise en œuvre pour doToString() dans la classe dérivée. Ceci est connu comme le modèle de conception Template Method.

Cependant, si vous êtes à la recherche d'un moyen de exigent l'implémenteur d'une classe dérivée d'appeler base.ToString() dans sa mise en œuvre de ToString(), alors il n'y a aucun moyen de le faire. En autorisant une substitution, vous donnez le contrôle de la classe dérivée sur son implémentation.

Vous pouvez documenter votre recommandation pour toujours appeler base.ToString(), mais c'est à peu près tout.

L'utilisation d'une interface définit le contrat public pour votre classe. Cela ne vous donne aucun avantage supplémentaire sur le modèle de méthode de modèle, car vous devez toujours dériver d'une classe de base pour obtenir l'implémentation "par défaut".

Avez-vous des détails sur ce que vous essayez de fournir dans votre classe de base comme "comportement par défaut"? Peut-être que cela aidera à trouver une meilleure solution. En regardant la question référencée, c'est essentiellement la même approche.

+0

Merci, votre édition m'a fait réaliser quelque chose d'important! Même si je trouverais un moyen miracle de définir ToString() dans la classe de base et forcer le remplacement dans la classe dérivée, il n'y a tout simplement pas moyen de forcer le override à utiliser ToString()! J'ai également trouvé ce poste par un MVP sur le forçage de substitution: http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/c25b6477-b990-4284-abaf-801ddf18207c. Merci encore monsieur. – Tipx

+0

Content d'être utile. Ce message est de Marc Gravell ... il est bien connu sur SO aussi :) –

+0

Comment cela se compare-t-il avec la réponse OP affichée ci-dessous? – Armbrat

0

Non, il n'est pas possible de transformer une fonction actuellement virtuelle en une fonction abstraite. La seule façon d'imposer cela serait de créer une autre fonction abstraite, comme vous l'avez suggéré. C'est sans doute une approche plus appropriée (et je suis d'accord avec cela).

2

Je viens de découvrir ce qu'il faut faire pour obtenir exactement le comportement que je voulais:

public abstract class AAA 
{ 
    protected abstract string ToStringSpecific(); 
    protected string ToString() 
    { 
    // Base Stuff 
    ... 
    // Use this.ToStringSpecific(); 
    } 
} 

public class BBB : AAA 
{ 
    protected override string ToStringSpecific() 
    { 
    // Specific Stuff 
    } 
} 
+0

Je pense que vous auriez dû éditer votre question originale ... – Armbrat

+0

Je vais en effet éditer la question (et le titre) afin qu'il puisse aider quelqu'un à trouver ce sujet, mais je vais laisser ma solution ici. (Si cela ne devrait pas être fait de cette façon, il n'y aurait pas de bouton "Anwser Your Question") – Tipx

+0

Je viens de relire la deuxième partie de mon commentaire et ça "sonne" arrogant. Je suis désolé pour cela, je ne voulais pas être, et je ne peux pas éditer le commentaire. Je m'excuse. – Tipx