Cela peut être une question générique de POO. Je voulais faire une comparaison générique entre une interface et une classe abstraite sur la base de leur utilisation.
Quand voudrait-on utiliser une interface et quand voudrait-on utiliser une classe abstraite ?
oop
inheritance
interface
abstract-class
Chirantan
la source
la source
Réponses:
J'ai écrit un article à ce sujet:
Classes abstraites et interfaces
Résumant:
Lorsque nous parlons de classes abstraites, nous définissons les caractéristiques d'un type d'objet; spécifiant ce qu'est un objet .
Lorsque nous parlons d'une interface et définissons des capacités que nous promettons de fournir, nous parlons d'établir un contrat sur ce que l'objet peut faire.
la source
Interfaces do not express something like "a Doberman is a type of dog and every dog can walk" but more like "this thing can walk"
. MerciUse abstract classes and inheritance if you can make the statement “A is a B”. Use interfaces if you can make the statement “A is capable of [doing] as”
Une classe abstraite peut avoir un état ou une fonctionnalité partagée. Une interface n'est qu'une promesse de fournir l'état ou la fonctionnalité. Une bonne classe abstraite réduira la quantité de code qui doit être réécrite car sa fonctionnalité ou son état peuvent être partagés. L'interface n'a aucune information définie à partager
la source
Personnellement, je n'ai presque jamais besoin d'écrire des cours abstraits.
La plupart du temps, je vois des classes abstraites être (mal) utilisées, c'est parce que l'auteur de la classe abstraite utilise le modèle "Méthode de modèle".
Le problème avec la "méthode Template" est qu'elle est presque toujours rentrante - la classe "dérivée" connaît non seulement la méthode "abstraite" de sa classe de base qu'elle implémente, mais aussi les méthodes publiques de la classe de base , même si la plupart du temps il n'a pas besoin de les appeler.
Exemple (trop simplifié):
Donc, ici, l'auteur de cette classe a écrit un algorithme générique et a l'intention que les gens l'utilisent en le "spécialisant" en fournissant leurs propres "hooks" - dans ce cas, une méthode "compare".
Donc, l'utilisation prévue est quelque chose comme ceci:
Le problème est que vous avez indûment couplé deux concepts:
Dans le code ci-dessus, théoriquement, l'auteur de la méthode "compare" peut rappeler de manière réentrante dans la méthode "Sort" de la superclasse ... même si en pratique ils ne voudront ou n'auront jamais besoin de le faire.
Le prix que vous payez pour ce couplage inutile est qu'il est difficile de changer la superclasse, et dans la plupart des langues OO, impossible de la changer au moment de l'exécution.
La méthode alternative consiste à utiliser le modèle de conception "Stratégie" à la place:
Alors remarquez maintenant: tout ce que nous avons, ce sont des interfaces et des implémentations concrètes de ces interfaces. En pratique, vous n'avez pas vraiment besoin d'autre chose pour faire une conception OO de haut niveau.
Pour "masquer" le fait que nous avons implémenté le "tri des noms" en utilisant une classe "QuickSort" et un "NameComparator", nous pourrions encore écrire une méthode d'usine quelque part:
Chaque fois que vous avez une classe abstraite, vous pouvez le faire ... même lorsqu'il existe une relation de ré-entrée naturelle entre la classe de base et la classe dérivée, il est généralement avantageux de les rendre explicites.
Une dernière pensée: tout ce que nous avons fait ci-dessus est de "composer" une fonction "NameSorting" en utilisant une fonction "QuickSort" et une fonction "NameComparison" ... dans un langage de programmation fonctionnel, ce style de programmation devient encore plus naturel, avec moins de code.
la source
Si vous regardez Java comme langage OOP,
"L' interface ne fournit pas d'implémentation de méthode " n'est plus valide avec le lancement de Java 8. Maintenant, java fournit une implémentation dans l'interface pour les méthodes par défaut.
En termes simples, je voudrais utiliser
interface: pour mettre en œuvre un contrat par plusieurs objets indépendants. Il offre lacapacité" A A ".
classe abstraite: pour implémenter un comportement identique ou différent parmi plusieurs objets associés. Il établit une relation" EST A ".
Le site Web Oracle fournit les principales différences entre
interface
et laabstract
classe.Envisagez d'utiliser des classes abstraites si:
Envisagez d'utiliser des interfaces si:
Serializable
interface.Exemple:
Classe abstraite ( est une relation)
Reader est une classe abstraite.
BufferedReader est un
Reader
FileReader est un
Reader
FileReader
etBufferedReader
sont utilisés dans un but commun: lire des données, et ils sont liés à travers laReader
classe.Interface ( capacité A A )
Serializable est une interface.
Supposons que vous avez deux classes dans votre application, qui implémentent une
Serializable
interfaceEmployee implements Serializable
Game implements Serializable
Ici, vous ne pouvez pas établir de relation via l'
Serializable
interface entreEmployee
etGame
, qui sont destinés à des fins différentes. Les deux sont capables de sérialiser l'état et la comparaison s'arrête là.Jetez un œil à ces articles:
Comment aurais-je dû expliquer la différence entre une interface et une classe abstraite?
la source
D'accord, juste après avoir "grokké" cela - ici c'est en termes profanes (n'hésitez pas à me corriger si je me trompe) - je sais que ce sujet est oooooold, mais quelqu'un d'autre pourrait tomber dessus un jour ...
Les classes abstraites vous permettent de créer un plan directeur et vous permettent en outre de CONSTRUIRE (implémenter) les propriétés et les méthodes que vous souhaitez que TOUS ses descendants possèdent.
Une interface, d'autre part, vous permet uniquement de déclarer que vous souhaitez que des propriétés et / ou des méthodes avec un nom donné existent dans toutes les classes qui l'implémentent - mais ne spécifie pas comment vous devez l'implémenter. En outre, une classe peut implémenter de NOMBREUSES interfaces, mais ne peut étendre qu'une seule classe abstraite. Une interface est plus un outil architectural de haut niveau (qui devient plus clair si vous commencez à saisir les modèles de conception) - un résumé a un pied dans les deux camps et peut également effectuer une partie du sale boulot.
Pourquoi utiliser l'un sur l'autre? Le premier permet une définition plus concrète des descendants - le second permet un plus grand polymorphisme . Ce dernier point est important pour l'utilisateur final / codeur, qui peut utiliser ces informations pour implémenter l'AP I (nterface) dans une variété de combinaisons / formes pour répondre à leurs besoins.
Je pense que ce fut le moment de "l'ampoule" pour moi - pensez aux interfaces moins du point de vue de l'auteur et plus de celui de tout codeur venant plus tard dans la chaîne qui ajoute une implémentation à un projet ou étend une API.
la source
Mes deux centimes:
Une interface définit fondamentalement un contrat auquel toute classe d'implémentation doit adhérer (implémenter les membres de l'interface). Il ne contient aucun code.
D'un autre côté, une classe abstraite peut contenir du code, et il peut y avoir certaines méthodes marquées comme abstraites qu'une classe héritée doit implémenter.
Les rares situations dans lesquelles j'ai utilisé des classes abstraites sont lorsque j'ai des fonctionnalités par défaut que la classe héritière peut ne pas être intéressante pour remplacer, par exemple une classe de base abstraite, dont héritent certaines classes spécialisées.
Exemple (un très rudimentaire!): Considérons une classe de base appelée client qui a des méthodes abstraites comme
CalculatePayment()
,CalculateRewardPoints()
et certaines méthodes non abstraites commeGetName()
,SavePaymentDetails()
.Les classes spécialisées aiment
RegularCustomer
etGoldCustomer
hériteront de laCustomer
classe de base et implémenteront leur propre logique de méthodeCalculatePayment()
etCalculateRewardPoints()
, mais réutilisent les méthodesGetName()
etSavePaymentDetails()
.Vous pouvez ajouter plus de fonctionnalités à une classe abstraite (c'est-à-dire des méthodes non abstraites) sans affecter les classes enfants qui utilisaient une ancienne version. Alors que l'ajout de méthodes à une interface affecterait toutes les classes qui l'implémentent, car elles devraient désormais implémenter les nouveaux membres de l'interface.
Une classe abstraite avec tous les membres abstraits serait similaire à une interface.
la source
Quand faire ce qui est très simple si le concept est clair dans votre esprit.
Les classes abstraites peuvent être dérivées tandis que les interfaces peuvent être implémentées. Il y a une différence entre les deux. Lorsque vous dérivez une classe abstraite, la relation entre la classe dérivée et la classe de base est une relation «est une». Par exemple, un chien est un animal, un mouton est un animal, ce qui signifie qu'une classe dérivée hérite de certaines propriétés de la classe de base.
Alors que pour l'implémentation des interfaces, la relation est "peut être". par exemple, un chien peut être un chien espion. Un chien peut être un chien de cirque. Un chien peut être un chien de course. Ce qui signifie que vous implémentez certaines méthodes pour acquérir quelque chose.
J'espère que je suis clair.
la source
1.Si vous créez quelque chose qui fournit des fonctionnalités communes à des classes indépendantes, utilisez une interface.
2.Si vous créez quelque chose pour des objets qui sont étroitement liés dans une hiérarchie, utilisez une classe abstraite.
la source
J'ai écrit un article sur quand utiliser une classe abstraite et quand utiliser une interface. Il y a beaucoup plus de différence entre eux que "un IS-A ... et un CAN-DO ...". Pour moi, ce sont des réponses en conserve. Je mentionne quelques raisons d'utiliser l'un ou l'autre. J'espère que cela aide.
http://codeofdoom.com/wordpress/2009/02/12/learn-this-when-to-use-an-abstract-class-and-an-interface/
la source
Je pense que la façon la plus succincte de le dire est la suivante:
Propriétés partagées => classe abstraite.
Fonctionnalité partagée => interface.
Et pour le dire moins succinctement ...
Exemple de classe abstraite:
Puisque les animaux ont une propriété partagée - nombre de pattes dans ce cas - il est logique de créer une classe abstraite contenant cette propriété partagée. Cela nous permet également d'écrire du code commun qui fonctionne sur cette propriété. Par exemple:
Exemple d'interface:
Notez ici que Vuvuzelas et Cars sont des choses complètement différentes, mais ils ont des fonctionnalités partagées: faire du son. Ainsi, une interface est logique ici. De plus, cela permettra aux programmeurs de regrouper des choses qui produisent des sons ensemble sous une interface commune -
IMakeSound
dans ce cas. Avec cette conception, vous pouvez écrire le code suivant:Pouvez-vous dire ce que cela produirait?
Enfin, vous pouvez combiner les deux.
Exemple combiné:
Ici, nous demandons à tous de
BaseAnimal
faire un son, mais nous ne connaissons pas encore sa mise en œuvre. Dans un tel cas, nous pouvons résumer l'implémentation de l'interface et déléguer son implémentation à ses sous-classes.Un dernier point, rappelez-vous comment dans l'exemple de classe abstraite, nous avons pu opérer sur les propriétés partagées de différents objets et dans l'exemple d'interface, nous avons pu invoquer la fonctionnalité partagée de différents objets? Dans ce dernier exemple, nous pourrions faire les deux.
la source
Quand préférer une classe abstraite à une interface?
Quand préférer une interface à une classe abstraite?
la source
Les classes peuvent hériter d'une seule classe de base, donc si vous souhaitez utiliser des classes abstraites pour fournir un polymorphisme à un groupe de classes, elles doivent toutes hériter de cette classe. Les classes abstraites peuvent également fournir des membres qui ont déjà été implémentés. Par conséquent, vous pouvez garantir une certaine quantité de fonctionnalités identiques avec une classe abstraite, mais pas avec une interface.
Voici quelques recommandations pour vous aider à décider d'utiliser une interface ou une classe abstraite pour fournir le polymorphisme à vos composants.
Copié depuis:
http://msdn.microsoft.com/en-us/library/scsyfw1d%28v=vs.71%29.aspx
la source
Envisagez d'utiliser des classes abstraites si l'une de ces déclarations s'applique à votre situation:
Envisagez d'utiliser des interfaces si l'une de ces déclarations s'applique à votre situation:
La source
la source
Les réponses varient selon les langues. Par exemple, en Java, une classe peut implémenter (hériter de) plusieurs interfaces mais hériter uniquement d'une classe abstraite. Les interfaces vous offrent donc plus de flexibilité. Mais ce n'est pas vrai en C ++.
la source
Pour moi, j'irais avec des interfaces dans de nombreux cas. Mais je préfère les classes abstraites dans certains cas.
Les classes en OO se réfèrent généralement à l'implémentation. J'utilise des classes abstraites lorsque je veux forcer certains détails d'implémentation aux enfants, sinon je vais avec des interfaces.
Bien sûr, les classes abstraites sont utiles non seulement pour forcer l'implémentation mais aussi pour partager certains détails spécifiques entre de nombreuses classes liées.
la source
Utilisez une classe abstraite si vous souhaitez fournir des implémentations de base.
la source
en java, vous pouvez hériter d'une classe (abstraite) pour "fournir" des fonctionnalités et vous pouvez implémenter de nombreuses interfaces pour "assurer" des fonctionnalités
la source
Purement sur la base de l'héritage, vous utiliseriez un résumé où vous définissez clairement des relations abstraites descendantes (c.-à-d. Animal-> chat) et / ou nécessitez l'héritage de propriétés virtuelles ou non publiques, en particulier l'état partagé (que les interfaces ne peuvent pas prendre en charge ).
Vous devriez essayer de privilégier la composition (via l'injection de dépendances) plutôt que l'héritage là où vous le pouvez, et notez que les interfaces étant des contrats prennent en charge les tests unitaires, la séparation des préoccupations et l'héritage multiple (variable selon la langue) d'une manière que les résumés ne peuvent pas.
la source
Un endroit intéressant où les interfaces s'en sortent mieux que les classes abstraites est lorsque vous devez ajouter des fonctionnalités supplémentaires à un groupe d'objets (liés ou non). Si vous ne pouvez pas leur donner une classe abstraite de base (par exemple, ils sont
sealed
ou ont déjà un parent), vous pouvez leur donner une interface factice (vide) à la place, puis simplement écrire des méthodes d'extension pour cette interface.la source
Cela peut être un appel très difficile à faire ...
Un pointeur que je peux donner: un objet peut implémenter de nombreuses interfaces, tandis qu'un objet ne peut hériter que d'une classe de base (dans un langage OO moderne comme c #, je sais que C ++ a plusieurs héritages - mais n'est-ce pas mal vu?)
la source
Une classe abstraite peut avoir des implémentations.
Une interface n'a pas d'implémentations, elle définit simplement une sorte de contrat.
Il peut également y avoir des différences dépendantes du langage: par exemple, C # n'a pas d'héritage multiple, mais plusieurs interfaces peuvent être implémentées dans une classe.
la source
La règle de base est la suivante: pour les "noms", utilisez la classe abstraite et pour les "verbes", utilisez l'interface
Par exemple:
car
est une classe abstraite etdrive
, nous pouvons en faire une interface.la source
drive
dans la voiture - c'est une classe abstraite.