2010-07-17 18 views
2

Dans l'exemple suivant, la classe Derived implémente la méthode abstraite method de la classe Main. Mais je ne peux pas penser à une raison pour remplir le corps de la méthode dans l'implémentation de la classe Derived. Je ne devrais sûrement que mettre en œuvre des méthodes abstraites dans des classes réelles.Pourquoi une classe abstraite devrait-elle implémenter une méthode abstraite d'une classe de base abstraite?

Alors, comment puis-je éviter de le faire? Que puis-je faire d'autre?

abstract class Main 
{ 
    public abstract void method(); 
} 
abstract class Derived : Main 
{ 
    public override void method() 
    { 
    } 
} 

class RealClass : Derived 
{ 

} 
+0

Je ne comprends pas quelle réponse vous voulez? Pouvez-vous s'il vous plaît expliquer votre question en détail? – YoK

+0

"Mais je ne trouve pas de raison de remplir à l'intérieur du corps de la méthode dans la classe abstraite dérivée." Cette citation est ma question. – Freshblood

Répondre

9

Habituellement, si quelqu'un a spécifié qu'une classe abstraite a une méthode abstraite, c'est soit parce que cette classe dépend de cette méthode pour une partie de ce qu'elle fait, soit parce que cela fait partie d'une API attendue pour la classe parent à mettre en œuvre à ce moment. Dans les deux cas, doit être une implémentation une fois que vous arrivez à une implémentation non-abstraite de la classe.

Notez également que si vous implémentez une interface , vous devez indiquer comment cette interface sera mise en œuvre, même si vous appelez simplement l'abstrait membre et passer la responsabilité sur la sous-classe

public interface IPet {string GetNoise(); int CountLegs(); void Walk();} 
public abstract class Pet : IPet 
{ 
    public string Name {get; set;} 
    public abstract string GetNoise(); // These must be here 
    public abstract int CountLegs(); 
    public abstract void Walk(); 
} 

Quand il s'agit de mettre en œuvre la sous-classe, vous avez quelques choix selon les circonstances. Si votre implémentation est elle-même une classe abstraite, vous ne devriez pas avoir besoin d'implémenter la méthode abstraite.

public abstract class Quadruped : Pet 
{ 
    public override int CountLegs() { return 4; } 
} 

Si votre mise en œuvre est non abstraite, mais la raison standard pour la méthode en question ne vraiment pas appliquer dans votre cas, vous pouvez faire une méthode no-op (dans le cas des méthodes vides), ou renvoyer une valeur fictive, ou même lancer une exception NotImplementedException pour indiquer que la méthode n'aurait jamais dû être appelée en premier lieu.

public class Fish : Pet 
{ 
    public override string GetNoise() {return "";} // dummy value: fish don't make noise 
    public override int CountLegs() {return 0;} 
    public override void Walk() {} // No-op 
    // public override void Walk() { throw new NotImplementedException("Fish can't walk"); } 
} 

Est-ce que cela répond à votre question?

+4

+1, bonne réponse. Strictement parlant, je pense que la méthode 'CountLegs' dans' Quadruped' devrait être scellée, ou n'importe qui sera capable de créer un quadrupède avec 3 pattes;) –

+0

Bonne réponse. Oui c'est une réponse de question. En utilisant l'aide d'interface pour surmonter ce problème. – Freshblood

+0

Une autre solution peut être de simplement définir la méthode Main comme virtuelle et de la remplir simplement pour la classe réelle, donc je n'aurai pas besoin de l'implémenter sur les classes abstraites enfant. – Freshblood

4

S'il n'y a pas la mise en œuvre de method à Derived alors vous pouvez juste faire Derived abstrait ainsi:

abstract class Derived : Main 
{ 
} 

class RealClass : Derived 
{ 
    public override void method() { ... } 
} 

EDIT: Pour clarifier les commentaires - s'il n'y a pas mise en œuvre effective d'une méthode abstraite une sous-classe, alors on n'a pas besoin d'être fourni. Cela nécessitera cependant que la classe dérivée soit elle-même abstraite et qu'une implémentation soit fournie quelque part dans la chaîne des classes descendantes à une sous-classe concrète. Je ne dis pas que vous devriez laisser l'implémentation de method vide, comme c'est dans la question, mais plutôt vous supprimez le remplacement dans Derived et marquez le résumé de la classe. Cela oblige RealClass à fournir une implémentation (ou elle-même être marquée abstraite).

+0

J'ai mis à jour la question. Déjà Derived était abstrait dans mon exemple mais je l'ai oublié d'écrire. Mais encore VS2010 implémenter la classe de méthode. – Freshblood

+0

@Freshblood - Vous ne pouvez pas fournir d'implémentation de 'method' dans' Derived'. Seules les classes concrètes doivent fournir des implémentations de tous les membres abstraits (directement ou indirectement via leurs classes parentes). – Lee

+0

Donc, la meilleure chose à faire est de laisser le corps de la méthode vide dans les classes dérivées? Si la méthode renvoie une valeur, nous devons lui renvoyer une valeur nulle ou une valeur, donc ce n'est pas une bonne conception. Je cherche un meilleur. – Freshblood

0

Toutes les classes descendantes non abstraites doivent fournir des implémentations concrètes de méthodes abstraites. Si vous ne fournissez pas une implémentation, il est impossible d'appeler cette méthode.

Si certaines classes concrètes ne présentent pas une implémentation correcte évidente d'une méthode abstraite, la conception de votre objet est incorrecte. Peut-être que vous devriez avoir une classe abstraite avec quelques méthodes abstraites (mais pas toutes). Cette classe pourrait avoir à la fois un descendant abstrait et des descendants concrets.