Conception d’inheritance utilisant Interface + classe abstraite. Bonnes pratiques?

Je ne sais pas trop comment donner un titre à cette question, mais j’ai essentiellement une interface comme celle-ci:

public interface IFoo { ssortingng ToCMD(); } 

quelques classes absract qui implémentent IFoo comme:

 public abstract class Foo : IFoo { public abstract ssortingng ToCMD(); } public abstract class Bar : IFoo { public abstract ssortingng ToCMD(); } 

puis les classes qui héritent de Foo et Bar:

 public class FooClass1 : Foo { public override ssortingng ToCMD() {return "Test";} } ///there are about 10 foo classes. public class BarClass : Bar { public override ssortingng ToCMD() {return "BarClass";} } ///about the same for bar classes. 

Je le fais de sorte que lorsque j’ai ma liste personnalisée comme:

 public class Store : List where T : IFoo {} 

Je peux alors restreindre les types qui y sont entrés mais en ayant l’interface, il faudra toujours n’importe quel type d’IFoo.

Quelque chose comme:

 Store store = new Store(); //Only Foo types will work. store.Add(new FooClass1()); //Will comstack. Store store = new Store(); //All IFoo types will work. store.Add(new FooClass1()); //Will comstack. store.Add(new BarClass()); //Will comstack. 

Ma question est la suivante: est-ce une bonne façon de procéder? ou y a-t-il un meilleur moyen?

EDIT: Image-> texte alternatif

La nécessité d’une chaîne d’inheritance est discutable, en général.

Cependant, le scénario spécifique consistant à combiner une classe de base abstraite avec une interface .. Je le vois ainsi:

Si vous avez une classe de base abstraite comme celle-ci, vous devriez également avoir une interface correspondante. Si vous avez une interface, utilisez la classe de base abstraite uniquement lorsque la chaîne d’inheritance est sensible.

Cela dit, si j’écris une bibliothèque et que cela fait partie de mon API / Framework, j’inclurai généralement une “implémentation par défaut” pouvant être utilisée comme classe de base. Il implémentera les méthodes d’interface d’une manière générale naïve, si possible, et laissera le rest aux héritiers pour implémenter / remplacer si nécessaire.

Il ne s’agit cependant que d’une fonctionnalité pratique de la bibliothèque, destinée à aider les personnes qui souhaitent implémenter l’interface en fournissant un exemple fonctionnel pouvant couvrir la plupart de ce qu’elles ont déjà besoin de mettre en œuvre.

En bref, l’interface est plus utile que la classe de base, mais une classe de base peut économiser beaucoup de temps et réduire les implémentations d’interface boguées.

Eh bien, c’est ce que le mot-clé where est pour. Vous devrez probablement évaluer votre modèle object pour vous assurer que la profondeur de votre inheritance est nécessaire. Les hiérarchies d’inheritance profonds ont tendance à compliquer les projets et sont généralement un drapeau rouge, mais cela dépend de la situation.

Habituellement, vous n’avez pas besoin de la classe abstraite pour extraire la fonctionnalité dont vous parlez avec les listes, et les interfaces sont la méthode «recommandée» pour spécifier les ressortingctions de type. Je n’utiliserais la version abstraite de votre classe que si vous souhaitez encapsuler une fonctionnalité commune.

Réponse courte : assurez-vous que votre pasortingmoine ne vous rend pas fou.

J’espère que cela pourra aider!

Vous pouvez également simplement utiliser des interfaces. Il n’y a aucune raison d’utiliser une classe abstraite.

 public interface Foo : IFoo { } public interface Bar : IFoo { } 

vous avez besoin de l’interface; vous pouvez ou non avoir besoin de la classe abstraite.

En général, si vous pouvez fournir un comportement utile dans une classe de base, fournissez une classe de base. si la classe de base n’est pas complète par elle-même, alors abstenez-vous (MustInherit en langage VB)

sinon, l’interface est suffisante

Je ne suis pas tout à fait sûr de savoir si c’est ce que vous cherchez, mais peut-être que vous voulez faire, c’est supprimer l’interface tout à la fois et procéder ainsi:

 abstract class Base { public abstract ssortingng ToCMD(); } abstract class Foo : Base { } abstract class Bar : Base { } 

J’espère que vous avez d’autres membres dans les classes Foo et Bar ! Cela vous permettra soit de restreindre votre collection personnalisée par Base soit simplement d’utiliser une List simple List .