web-dev-qa-db-fra.com

Classe abstraite vs interface en Java

On m'a posé une question, je voulais que ma réponse soit revue ici.

Q: Dans quel scénario il est plus approprié d’étendre une classe abstraite plutôt que de mettre en œuvre la ou les interfaces?

A: Si nous utilisons un modèle de conception de méthode de modèle.

Ai-je raison ?

Je suis désolé si je n’ai pas pu formuler 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 qu'il est nécessaire d'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 (signatures de méthode uniquement) 

2) utilisez l’interface si vous souhaitez que la signature soit identique (et différente de la mise en œuvre) pour pouvoir vous conformer à la mise en oeuvre de l’interface 

3) on peut étendre au maximum une classe abstraite, mais peut implémenter plus d'une interface 

Réitérant la question: Existe-t-il d’autres scénarios, en plus de ceux mentionnés ci-dessus, dans lesquels nous devons spécifiquement utiliser une classe abstraite (l’un est de voir si le modèle de conception de la méthode de modèle est basé sur ce concept uniquement)?

Interface vs classe abstraite

Le choix entre ces deux options 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, le seul moyen d'éviter cela serait donc de créer une toute nouvelle interface, ce qui pourrait ne pas toujours être une bonne chose. .

Abstract classes devrait principalement être utilisé pour des objets étroitement liés. Interfaces fournit mieux des fonctionnalités communes pour les classes non liées.

73
Java Geek

Quand utiliser les interfaces

Une interface permet à quelqu'un de commencer à 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'accidentelle, ce qui doit être ajouté à leur code pour pouvoir utiliser votre paquet. L'inconvénient est que chaque méthode de l'interface doit être publique. Vous pourriez ne pas vouloir tout exposer.

Quand utiliser les 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 problème, 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 paquet ont déjà développé leur propre hiérarchie de classes de manière indépendante. En Java, une classe ne peut hériter que d’une classe de base.

Quand utiliser les deux

Vous pouvez offrir le meilleur des deux mondes, une interface et une classe abstraite. Les développeurs peuvent ignorer votre classe abstraite s'ils le souhaitent. Le seul inconvénient est que l'appel de méthodes via leur nom d'interface est légèrement plus lent que leur appel via leur nom de classe abstraite. 

73
DivineDesert

réitérant la question: il existe un autre scénario en plus de ceux mentionnés ci-dessus dans lesquels nous devons spécifiquement utiliser une classe abstraite (l'un est voir si le modèle de conception de méthode de modèle est basé sur ce concept uniquement)

Oui, si vous utilisez JAXB. Il n'aime pas les interfaces. Vous devez utiliser des classes abstraites ou contourner cette limitation avec des génériques.

D'un blog personnel post :

Interface:

  1. Une classe peut implémenter plusieurs interfaces
  2. Une interface ne peut fournir aucun code
  3. Une interface ne peut définir que des constantes finales statiques publiques
  4. Une interface ne peut pas définir de variables d'instance
  5. L'ajout d'une nouvelle méthode a des effets d'entraînement sur l'implémentation de classes (maintenance de la conception)
  6. JAXB ne peut pas gérer les interfaces
  7. Une interface ne peut pas étendre ou implémenter une classe abstraite
  8. Toutes les méthodes d'interface sont publiques

En général, les interfaces doivent être utilisées pour définir les contrats (ce qui doit être réalisé, et non pas comment le réaliser).

Classe abstraite:

  1. Une classe peut s'étendre au plus une classe abstraite
  2. Une classe abstraite peut contenir du code
  3. Une classe abstraite peut définir des constantes statiques et d'instance (final)
  4. Une classe abstraite peut définir des variables d'instance
  5. La modification du code de classe abstrait existant a des effets d'entraînement sur les classes d'extension (maintenance de la mise en oeuvre)
  6. L'ajout d'une nouvelle méthode à une classe abstraite n'a pas d'effet d'entraînement sur l'extension des classes
  7. Une classe abstraite peut implémenter une interface
  8. Les classes abstraites peuvent implémenter des méthodes privées et protégées

Les classes abstraites doivent être utilisées pour une implémentation (partielle). Ils peuvent constituer un moyen de restreindre la manière dont les contrats d'API doivent être mis en œuvre.

27
Jérôme Verstrynge

L'interface est utilisée lorsque vous avez un scénario selon lequel toutes les classes ont la même structure mais présentent des fonctionnalités totalement 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 sont identiques.

Jetez un coup d'œil à l'article: http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html

10
SMK

Lequel devriez-vous utiliser, des classes abstraites ou des interfaces?

Envisagez d'utiliser des classes abstraites si l'une de ces déclarations s'applique à votre scénario:

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 public (tels que protected et private).

Vous voulez déclarer des champs non statiques ou non finaux. Cela vous permet de définir des méthodes pouvant accéder à et modifier l'état de l'objet auquel elles appartiennent.

Envisagez d'utiliser des interfaces si l'une de ces déclarations s'applique à votre situation:

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 non liées.

Vous souhaitez spécifier le comportement d'un type de données particulier, sans vous soucier de savoir qui l'implémente.

Vous souhaitez tirer parti de l'héritage multiple de type.

http://docs.Oracle.com/javase/tutorial/Java/IandI/abstract.html

4
Santh

Les choses ont beaucoup changé au cours des trois dernières années avec l’ajout de nouvelles fonctionnalités d’interface avec Java 8. 

De la documentation Oracle page sur l'interface:

Une interface est un type de référence, similaire à une classe, qui ne peut contenir que des constantes, des signatures de méthodes, des méthodes default, des méthodes statiques et des types imbriqués. Les corps de méthodes n'existent que pour les méthodes par défaut et les méthodes statiques.

Comme vous l'avez indiqué dans votre question, la classe abstraite convient le mieux à modèle de méthode de modèle dans lequel 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 puisque vous souhaitez partager un é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 des classes non liées.


Deuxième partie de votre question, valable pour la plupart des langages de programmation, y compris Java, antérieure à la version Java-8.

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 modifier une interface sans avoir à changer beaucoup de choses dans votre code

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 en tant que méthodes par défaut ont ajouté de puissantes fonctionnalités aux interfaces. 

Les méthodes par défaut vous permettent d'ajouter de nouvelles fonctionnalités aux interfaces de vos bibliothèques et d'assurer la compatibilité binaire avec le code écrit pour les versions antérieures de ces interfaces.

Pour sélectionner l'un d'entre eux entre l'interface et la classe abstraite, consultez la documentation Oracle page quote qui:

Les classes abstraites sont similaires aux interfaces. Vous ne pouvez pas les instancier, et elles peuvent contenir un mélange de méthodes déclarées avec ou sans implémentation. Toutefois, avec les classes abstraites, vous pouvez déclarer des champs non statiques et finaux et définir des méthodes concrètes publiques, protégées et privées. 

Avec les interfaces, tous les champs sont automatiquement publics, statiques et finaux, et toutes les méthodes que vous déclarez ou définissez (en tant que méthodes par défaut) sont publiques. De plus, vous ne pouvez étendre qu'une seule classe, qu'elle soit abstraite ou non, alors que vous pouvez implémenter un nombre illimité d'interfaces.

Reportez-vous à ces questions connexes pour plus de détails: 

Interface vs Abstract Class (OO général)

Comment aurais-je dû expliquer la différence entre une classe d'interface et une classe abstraite?

En résumé: La balance penche davantage vers les interfaces}.

Existe-t-il d’autres scénarios, en plus de ceux mentionnés ci-dessus, dans lesquels nous avons spécifiquement besoin d’utiliser une classe abstraite (l’un est de voir si le modèle de conception de la méthode template est basé sur ce concept uniquement)?

Certains modèles de conception utilisent des classes abstraites (sur des interfaces) en plus du modèle de méthode Template. 

Modèles de création:

Abstract_factory_pattern

(Structures structurelles:} _

Decorator_pattern

Modèles comportementaux: 

Mediator_pattern

4
Ravindra babu

Vous n'êtes pas correct Il y a beaucoup de scénarios. Il n'est tout simplement pas possible de le réduire à une seule règle de 8 mots.

3
user207421

À 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-classes. 

J'ai également cité ce qui suit dans le livre "Conception de l'architecture logicielle en Java"

"Dans le langage de programmation Java, l'héritage multiple n'est pas pris en charge . 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. Chaque fois que cela est possible, les méthodes denoter le comportement commun doit être déclaré sous la forme d’une interface Java être implémenté par différentes classes d’implémentation. Mais les interfaces souffrent de la limitation de leur incapacité à fournir des implémentations de méthodes. 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 méthodes représentent la partie invariable de la fonctionnalité et ont exactement la même implémentation dans toutes les classes de l’implémenteur, ce qui conduit à un code redondant. L’exemple suivant montrecomment utiliser le modèle de classe parent abstraite dans de tels cas sans que Ne nécessite la mise en œuvre de méthodes redondantes. "

3
user2794921

La réponse la plus courte est extend abstract class lorsque certaines des fonctionnalités recherchées y sont déjà implémentées.

Si vous implémentez l'interface, vous devez implémenter toute la méthode. Mais pour les classes abstraites, le nombre de méthodes à implémenter peut être inférieur. 

Dans modèle de conception , un comportement doit être défini. Ce comportement dépend d'autres méthodes qui sont abstraites. En créant des sous-classes et en définissant ces méthodes, vous définissez le comportement principal. Le comportement sous-jacent ne peut pas être dans une interface car l'interface ne définit rien, elle se contente de déclarer. Ainsi, un modèle de conception de modèle vient toujours avec une classe abstraite. Si vous souhaitez conserver le flux du comportement intact, vous devez étendre la classe abstraite mais ne pas remplacer le comportement principal.

3
Shiplu Mokaddim

Les classes abstraites se distinguent des interfaces par deux aspects importants

  • ils fournissent une implémentation par défaut pour les méthodes choisies (couvertes par votre réponse)
  • les classes abstraites peuvent avoir un état (variables d'instance) - il s'agit donc d'une situation supplémentaire dans laquelle vous souhaitez les utiliser à la place d'interfaces
2
Piotr Kochański

Il y a beaucoup de bonnes réponses ici, mais je trouve souvent que le meilleur chemin consiste à utiliser les deux interfaces et classes abstraites. Considérons cet exemple artificiel:

Vous êtes développeur de logiciels dans une banque d’investissement et vous devez créer un système qui place les commandes sur le marché. Votre interface capture l’idée la plus générale de ce qu’un système commercial 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 point de vente et dans d’autres secteurs d’activité peuvent commencer à utiliser une interface avec votre système pour ajouter la fonctionnalité de placement des commandes à leurs applications existantes. Et vous n'avez même pas encore commencé à construire! C'est le pouvoir des interfaces.

Alors vous allez de l'avant et construisez le système pour stock traders; ils ont entendu dire que votre système dispose d'une fonctionnalité permettant de trouver des actions à bas prix et qu'ils sont très impatients de l'essayer! Vous capturez ce comportement dans une méthode appelée findGoodDeals(), mais vous réalisez également que la connexion aux marchés comporte de nombreux problèmes. Par exemple, vous devez ouvrir une SocketChannel,

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 compliquées comme connectToMarket(), mais findGoodDeals() est l’ensemble des préoccupations des traders.

Maintenant, voici où les classes abstraites entrent en jeu. Votre patron vous informe que les traders de devises veulent é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é intégralement pour se connecter aux marchés des changes. Cependant, findGoodDeals() est un concept très différent dans le domaine des devises. Donc, avant de transmettre la base de code au spécialiste des opérations de change à travers l’océan, vous devez d’abord réfléchir à une classe abstract, en laissant findGoodDeals() non 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 de négociation d'actions implémente findGoodDeals() 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 à présent, l’aspirant 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 ni 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 les méthodes de manière 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 COMPLETEMENT DIFFÉRENT, où ils ne se soucient pas de trouver de bonnes offres. L'interface garantit que le bureau des ventes peut également s'interfacer avec son système. Il est donc préférable de ne pas embrouiller votre interface avec des concepts d'application tels que "des offres exceptionnelles".

2
Adam Hughes

C'est une bonne question. Les deux ne sont pas similaires mais peuvent être utilisés pour les mêmes raisons, comme une réécriture. Lors de la création, il est préférable d'utiliser Interface. En classe, c'est bon pour le débogage. 

1
sharonda walker

Ceci est ma compréhension, espérons que cela aide

Classes abstraites:

  1. Peut avoir des variables de membre héritées (impossible dans les interfaces)
  2. Peut avoir des constructeurs (les interfaces ne peuvent pas)
  3. Ses méthodes peuvent avoir n'importe quelle visibilité (c'est-à-dire: privé, protégé, etc. alors que toutes les méthodes d'interface sont publiques)
  4. Peut avoir des méthodes définies (méthodes avec une implémentation)

Interfaces:

  1. Peut avoir des variables, mais ce sont toutes des variables finales statiques publiques
    • valeurs constantes qui ne changent jamais avec une portée statique
    • les variables non statiques nécessitent une instance et vous ne pouvez pas instancier une interface.
  2. Toutes les méthodes sont abstraites (pas de code dans les méthodes abstraites)
    • tout le code doit être réellement écrit dans la classe qui implémente l'interface particulière
0
zozep

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 le comportement spécifique de la méthode abstraite que les sous-classes doivent implémenter.

Interfaces allows you to change the implementation anytime allowing the interface to be intact.

0
Ramesh PVK

Utilisation du résumé et de l'interface:

L'un a "Est-Une-relation" et un autre a "Has-Une-relation"

Les propriétés par défaut sont définies dans abstract et des propriétés supplémentaires peuvent être exprimées via l'interface.

Exemple: -> Chez les êtres humains, nous avons certaines propriétés par défaut qui mangent, dorment, etc. mais si quelqu'un a d'autres activités comme la natation, le jeu, etc., celles-ci peuvent être exprimées par Interface.

0
user7439667

Différence entre la classe abstraite et l'interface

Classe abstraite

  • La classe abstraite peut avoir des méthodes abstraites et non abstraites
  • classe abstraite peut contenir des variables non finales
  • La classe abstraite peut avoir des variables finales, non finales, statiques et non statiques
  • La classe abstraite peut fournir l'implémentation d'interface
  • La classe abstraite peut être étendue en utilisant le mot-clé "expand"
  • Une classe abstraite peut étendre une autre classe Java et implémenter plusieurs interfaces Java
  • Une classe abstraite Java peut avoir des membres de classe comme privés, protégés, etc.

interfaces

  • L'interface ne peut avoir que des méthodes abstraites
  • Les variables déclarées dans une interface Java sont finales par défaut
  • L'interface n'a que des variables statiques et finales
  • L’interface ne permet pas l’implémentation de la classe abstraite
  • Une interface Java peut être implémentée à l'aide du mot clé "implément"
  • Une interface ne peut étendre qu'une autre interface Java
  • Les membres d'une interface Java sont publics par défaut
0
Malith Ileperuma