Quand utiliser des interfaces ou des classes abstraites? Quand utiliser les deux?

Alors que certaines lignes directrices que vous devez utiliser une interface lorsque vous souhaitez définir un contrat pour une classe où l'héritage n'est pas clair (IDomesticated) et de la succession lorsque la classe est une extension de l'autre (Cat : Mammal, Snake : Reptile), il ya des cas où (à mon avis) de ces lignes directrices entrer dans une zone grise.

Par exemple, dire que ma mise en œuvre a été Cat : Pet. Pet est une classe abstraite. Devrait-il être étendu à Cat : Mammal, IDomesticatedMammal est une classe abstraite et IDomesticated est une interface? Ou suis-je en conflit avec la KISS/YAGNI principes (même si je ne suis pas sûr qu'il y aura un Wolf classe dans l'avenir, ce qui ne serait pas en mesure d'hériter de Pet)?

Éloigner de la métaphorique Cats et Pets, disons que j'ai quelques classes qui représentent des sources de données entrants. Ils ont tous besoin de mettre en œuvre la même base, en quelque sorte. J'ai pu mettre en œuvre certains génériques de code dans un résumé Source classe et hériter d'elle. J'aurais aussi pu faire un ISource de l'interface (qui se sent plus "juste" pour moi) et de re-mettre en œuvre les génériques de code dans chaque classe (ce qui est moins intuitif). Enfin, je pourrais "avoir le gâteau et le manger" en faisant à la fois de la classe abstraite et de l'interface. Quel est le meilleur?

Ces deux cas, amener des points pour l'utilisation de seulement une classe abstraite, seulement une interface et une classe abstraite et une interface. Sont-ils tous des choix valables, ou il y a des "règles" pour quand on doit être utilisé sur un autre?


Je tiens à préciser que par "en utilisant à la fois une classe abstraite et une interface" qui inclut le cas lorsqu'ils représentent essentiellement la même chose (Source et ISource les deux ont les mêmes membres), mais la classe ajoute une fonctionnalité générique alors que l'interface spécifie le contrat.

Également intéressant de noter que cette question est surtout pour les langues qui ne supporte pas l'héritage multiple (tels que .NET et Java).

InformationsquelleAutor Blixt | 2009-08-05