On m'a posé une question, je voulais que ma réponse soit examinée ici.
Q: Dans quel scénario est-il plus approprié d'étendre une classe abstraite plutôt que d'implémenter la ou les interfaces?
R: Si nous utilisons un modèle de conception de méthode de modèle.
Ai-je raison ?
Je regrette de ne pas avoir pu énoncer clairement la question.
Je connais la différence fondamentale entre la classe abstraite et l'interface.
1) utiliser une classe abstraite lorsque l'exigence est telle que nous devons implémenter la même fonctionnalité dans chaque sous-classe pour une opération spécifique (implémenter la méthode) et une fonctionnalité différente pour certaines autres opérations (uniquement les signatures de méthode)
2) utilisez l'interface si vous devez mettre la signature de manière identique (et l'implémentation différente) afin de pouvoir vous conformer à l'implémentation de l'interface
3) nous pouvons étendre au maximum une classe abstraite, mais nous pouvons implémenter plus d'une interface
Réitérant la question: y a-t-il d'autres scénarios, en plus de ceux mentionnés ci-dessus, où nous avons spécifiquement besoin d'utiliser une classe abstraite (on voit que le modèle de conception de méthode de modèle est conceptuellement basé uniquement sur cela)?
Interface vs classe abstraite
Le choix entre ces deux dépend vraiment de ce que vous voulez faire, mais heureusement pour nous, Erich Gamma peut nous aider un peu.
Comme toujours, il y a un compromis, une interface vous donne la liberté par rapport à la classe de base, une classe abstraite vous donne la liberté d'ajouter de nouvelles méthodes plus tard . - Erich Gamma
Vous ne pouvez pas changer une interface sans avoir à changer beaucoup d'autres choses dans votre code, donc le seul moyen d'éviter cela serait de créer une toute nouvelle interface, ce qui n'est peut-être pas toujours une bonne chose.
Abstract classes
doit principalement être utilisé pour des objets étroitement liés. Interfaces
sont plus efficaces pour fournir des fonctionnalités communes aux classes non liées.
la source
Réponses:
Quand utiliser les interfaces
Une interface permet à quelqu'un de partir de zéro pour implémenter votre interface ou implémenter votre interface dans un autre code dont le but initial ou principal était assez différent de votre interface. Pour eux, votre interface n'est qu'accessoire, quelque chose qui doit s'ajouter à leur code pour pouvoir utiliser votre package. L'inconvénient est que chaque méthode de l'interface doit être publique. Vous pourriez ne pas vouloir tout exposer.
Quand utiliser des classes abstraites
Une classe abstraite, en revanche, fournit plus de structure. Il définit généralement certaines implémentations par défaut et fournit des outils utiles pour une implémentation complète. Le hic, c'est que le code qui l'utilise doit utiliser votre classe comme base. Cela peut être très gênant si les autres programmeurs souhaitant utiliser votre package ont déjà développé leur propre hiérarchie de classes indépendamment. En Java, une classe ne peut hériter que d'une seule classe de base.
Quand utiliser les deux
Vous pouvez offrir le meilleur des deux mondes, une interface et une classe abstraite. Les implémenteurs peuvent ignorer votre classe abstraite s'ils le souhaitent. Le seul inconvénient de faire cela est d'appeler des méthodes via leur nom d'interface est légèrement plus lent que de les appeler via leur nom de classe abstrait.
la source
If we are using template method design pattern
Nous ne pouvons pas direYES
ouNO
Oui, si vous utilisez JAXB. Il n'aime pas les interfaces. Vous devez soit utiliser des classes abstraites, soit contourner cette limitation avec des génériques.
À partir d' un blog personnel après :
Interface:
En général, les interfaces doivent être utilisées pour définir les contrats (ce qui doit être réalisé, pas comment y parvenir).
Classe abstraite:
Les classes abstraites doivent être utilisées pour une implémentation (partielle). Ils peuvent être un moyen de restreindre la manière dont les contrats API doivent être mis en œuvre.
la source
default
etstatic
.L'interface est utilisée lorsque vous avez un scénario selon lequel toutes les classes ont la même structure mais ont totalement des fonctionnalités différentes.
La classe abstraite est utilisée lorsque vous avez un scénario selon lequel toutes les classes ont la même structure mais certaines fonctionnalités identiques et différentes.
Jetez un œil à l'article: http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html
la source
Il y a beaucoup de bonnes réponses ici, mais je trouve souvent que l'utilisation des DEUX interfaces et des classes abstraites est la meilleure voie. Considérez cet exemple artificiel:
Vous êtes développeur de logiciels dans une banque d'investissement et devez créer un système qui place des ordres sur un marché. Interface capture de ce qu'est un système commercial plus idée générale fait ,
1) Trading system places orders 2) Trading system receives acknowledgements
et peut être capturé dans une interface,
ITradeSystem
public interface ITradeSystem{ public void placeOrder(IOrder order); public void ackOrder(IOrder order); }
Désormais, les ingénieurs travaillant au bureau des ventes et dans d'autres secteurs d'activité peuvent commencer à s'interfacer avec votre système pour ajouter des fonctionnalités de placement de commande à leurs applications existantes. Et vous n'avez même pas encore commencé à construire! C'est la puissance des interfaces.
Alors vous allez de l'avant et construisez le système pour les négociants en actions ; ils ont entendu dire que votre système a une fonction pour trouver des actions bon marché et sont très impatients de l'essayer! Vous capturez ce comportement dans une méthode appelée
findGoodDeals()
, mais vous réalisez également qu'il y a beaucoup de choses compliquées qui sont impliquées dans la connexion aux marchés. Par exemple, vous devez ouvrir unSocketChannel
,public class StockTradeSystem implements ITradeSystem{ @Override public void placeOrder(IOrder order); getMarket().place(order); @Override public void ackOrder(IOrder order); System.out.println("Order received" + order); private void connectToMarket(); SocketChannel sock = Socket.open(); sock.bind(marketAddress); <LOTS MORE MESSY CODE> } public void findGoodDeals(); deals = <apply magic wizardry> System.out.println("The best stocks to buy are: " + deals); }
Les implémentations concrètes vont avoir beaucoup de ces méthodes désordonnées
connectToMarket()
, maisfindGoodDeals()
c'est tout ce dont les traders se soucient réellement.Voici maintenant où les classes abstraites entrent en jeu. Votre patron vous informe que les traders de devises souhaitent également utiliser votre système. Et en regardant les marchés des devises, vous voyez que la plomberie est presque identique aux marchés boursiers. En fait,
connectToMarket()
peut être réutilisé textuellement pour se connecter aux marchés des changes. Cependant,findGoodDeals()
c'est un concept très différent dans l'arène monétaire. Donc, avant de transmettre la base de code à l'enfant sorcier des changes de l'autre côté de l'océan, vous commencez par refactoriser en uneabstract
classe, laissant nonfindGoodDeals()
implémentépublic abstract class ABCTradeSystem implements ITradeSystem{ public abstract void findGoodDeals(); @Override public void placeOrder(IOrder order); getMarket().place(order); @Override public void ackOrder(IOrder order); System.out.println("Order received" + order); private void connectToMarket(); SocketChannel sock = Socket.open(); sock.bind(marketAddress); <LOTS MORE MESSY CODE> }
Votre système boursier met
findGoodDeals()
en œuvre comme vous l'avez déjà défini,public class StockTradeSystem extends ABCTradeSystem{ public void findGoodDeals(); deals = <apply magic wizardry> System.out.println("The best stocks to buy are: " + deals); }
mais maintenant, la gamine fétiche FX peut construire son système en fournissant simplement une implémentation de
findGoodDeals()
pour les devises; elle n'a pas à réimplémenter les connexions socket ou même les méthodes d'interface!public class CurrencyTradeSystem extends ABCTradeSystem{ public void findGoodDeals(); ccys = <Genius stuff to find undervalued currencies> System.out.println("The best FX spot rates are: " + ccys); }
La programmation sur une interface est puissante, mais des applications similaires réimplémentent souvent des méthodes de manière presque identique. L'utilisation d'une classe abstraite évite les réimplémentations, tout en préservant la puissance de l'interface.
Remarque: on peut se demander pourquoi
findGreatDeals()
ne fait pas partie de l'interface. N'oubliez pas que l'interface définit les composants les plus généraux d'un système commercial. Un autre ingénieur peut développer un système commercial COMPLÈTEMENT DIFFÉRENT, où il ne se soucie pas de trouver de bonnes affaires. L'interface garantit que le bureau de vente peut également s'interfacer avec son système, il est donc préférable de ne pas enchevêtrer votre interface avec des concepts d'application tels que «bonnes affaires».la source
Lesquelles devez-vous utiliser, classes abstraites ou interfaces?
Envisagez d'utiliser des classes abstraites si l'une de ces instructions s'applique à votre cas d'utilisation:
Vous souhaitez partager du code entre plusieurs classes étroitement liées.
Vous vous attendez à ce que les classes qui étendent votre classe abstraite aient de nombreuses méthodes ou champs communs, ou nécessitent des modificateurs d'accès autres que publics (tels que protected et private).
Vous souhaitez déclarer des champs non statiques ou non finaux. Cela vous permet de définir des méthodes qui peuvent accéder et modifier l'état de l'objet auquel elles appartiennent.
Envisagez d'utiliser des interfaces si l'une de ces instructions s'applique à votre cas d'utilisation:
Vous vous attendez à ce que des classes non liées implémentent votre interface. Par exemple, les interfaces Comparable et Cloneable sont implémentées par de nombreuses classes indépendantes.
Vous souhaitez spécifier le comportement d'un type de données particulier, sans vous soucier de qui implémente son comportement.
Vous souhaitez profiter de l'héritage multiple de type.
http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
la source
Les choses ont beaucoup changé au cours des trois dernières années avec l'ajout de nouvelles fonctionnalités d'interface avec la version Java 8.
À partir de la page de documentation d'Oracle sur l'interface:
Comme vous l'avez mentionné dans votre question, la classe abstraite est la mieux adaptée pour le modèle de méthode modèle où vous devez créer un squelette. L'interface ne peut pas être utilisée ici.
Une autre considération pour préférer la classe abstraite à l'interface:
Vous n'avez pas d'implémentation dans la classe de base et seules les sous-classes doivent définir leur propre implémentation. Vous avez besoin d'une classe abstraite au lieu d'une interface car vous souhaitez partager l'état avec des sous-classes.
La classe abstraite établit "est une" relation entre les classes liées et l'interface fournit "a une" capacité entre les classes non liées .
En ce qui concerne la deuxième partie de votre question, ce qui est valable pour la plupart des langages de programmation , y compris java avant java-8 version
Si vous préférez que la classe abstraite s'interface plus tôt avec les deux considérations ci-dessus, vous devez repenser maintenant car les méthodes par défaut ont ajouté de puissantes capacités aux interfaces.
Pour sélectionner l'un d'entre eux entre l'interface et la classe abstraite, la page de documentation d'Oracle cite que:
Reportez-vous à ces questions connexes pour plus de détails:
Interface vs classe abstraite (OO général)
Comment aurais-je dû expliquer la différence entre une interface et une classe abstraite?
En résumé: la balance penche désormais davantage vers les interfaces .
Certains modèles de conception utilisent des classes abstraites (sur des interfaces) en dehors du modèle de méthode Template.
Modèles de création:
Abstract_factory_pattern
Modèles structurels:
Decorator_pattern
Modèles de comportement:
Mediator_pattern
la source
Vous n'avez pas raison. Il existe de nombreux scénarios. Il n'est tout simplement pas possible de le réduire à une seule règle de 8 mots.
la source
La réponse la plus courte est: étendre la classe abstraite lorsque certaines des fonctionnalités que vous recherchez y sont déjà implémentées.
Si vous implémentez l'interface, vous devez implémenter toute la méthode. Mais pour la classe abstraite, le nombre de méthodes que vous devez implémenter peut être inférieur.
Dans le modèle de conception de modèle , un comportement doit être défini. Ce comportement dépend d'autres méthodes qui sont abstraites. En créant une sous-classe et en définissant ces méthodes, vous définissez en fait le comportement principal. Le comportement sous-jacent ne peut pas être dans une interface car l'interface ne définit rien, elle le déclare simplement. Ainsi, un modèle de conception de modèle est toujours accompagné d'une classe abstraite. Si vous souhaitez conserver le flux du comportement intact, vous devez étendre la classe abstraite mais ne remplacez pas le comportement principal.
la source
Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contain only pure virtual functions, but no data members or ordinary methods.
partie (1/2)no data members or ordinary methods
[dans la classe abstraite].À mon avis, la différence fondamentale est que
an interface can't contain non abstract methods while an abstract class can
. Ainsi, si les sous-classes partagent un comportement commun, ce comportement peut être implémenté dans la super classe et donc hérité dans les sous-classesJ'ai également cité ce qui suit dans le livre "Software architecture design ppatterns in java"
"Dans le langage de programmation Java, il n'y a pas de support pour l'héritage multiple. Cela signifie qu'une classe ne peut hériter que d'une seule classe. Par conséquent, l'héritage ne doit être utilisé que lorsque cela est absolument nécessaire. Dans la mesure du possible, les méthodes dénotant le comportement commun doivent être déclarées dans sous la forme d'une interface Java à implémenter par différentes classes d'implémentation. Mais les interfaces souffrent de la limitation qu'elles ne peuvent pas fournir d'implémentations de méthode. Cela signifie que chaque implémenteur d'une interface doit implémenter explicitement toutes les méthodes déclarées dans une interface, même lorsque certaines de ces Les méthodes représentent la partie invariable de la fonctionnalité et ont exactement la même implémentation dans toutes les classes d'implémentation, ce qui conduit à un code redondant.L'exemple suivant montre comment le modèle de classe parent abstraite peut être utilisé dans de tels cas sans nécessiter d'implémentations de méthodes redondantes. "
la source
Les classes abstraites sont différentes des interfaces sur deux aspects importants
la source
C'est une bonne question. Les deux ne sont pas similaires mais peuvent être utilisées pour une partie de la même raison, comme une réécriture. Lors de la création, il est préférable d'utiliser Interface. Quand il s'agit de classe, c'est bon pour le débogage.
la source
Abstract classes should be extended when you want to some common behavior to get extended
. La super classe abstraite aura le comportement commun et définira une méthode abstraite / un comportement spécifique que les sous-classes devraient implémenter.Interfaces allows you to change the implementation anytime allowing the interface to be intact
.la source
C'est ma compréhension, j'espère que cela aide
Classes abstraites:
Interfaces:
la source
Utilisation du résumé et de l'interface:
L'un a "Is-A-Relationship" et un autre a "Has-A-Relationship"
Les propriétés par défaut ont été définies dans abstrait et des propriétés supplémentaires peuvent être exprimées via l'interface.
Exemple: -> Chez les êtres humains, nous avons des propriétés par défaut qui mangent, dorment, etc.
la source