web-dev-qa-db-fra.com

Interface avec les méthodes par défaut et la classe abstraite en Java 8

Comme Java 8 permet l’implémentation par défaut des méthodes dans l’interface appelée Méthodes par défaut , il semble exister une confusion entre quand utiliserais-je un abstract class.

Alors, quand faut-il utiliser l'interface avec les méthodes par défaut et quand utiliser une classe abstraite? Les classes abstraites sont-elles toujours utiles dans ce scénario? 

415
Narendra Pathai

Les classes abstraites représentent bien plus que des implémentations de méthodes par défaut (telles que private state), mais à partir de Java 8, chaque fois que vous avez le choix, vous devez utiliser la méthode defender (ou. default) dans l'interface.

La contrainte sur la méthode par défaut est qu'elle ne peut être implémentée qu'en termes d'appels à d'autres méthodes d'interface, sans référence à l'état d'une implémentation particulière. Le principal cas d'utilisation est donc les méthodes de niveau supérieur et de commodité.

La bonne chose à propos de cette nouvelle fonctionnalité est que, là où auparavant vous étiez obligé d'utiliser une classe abstraite pour les méthodes pratiques, contraignant ainsi l'implémenteur à un héritage unique, vous pouvez maintenant avoir une conception vraiment épurée avec juste l'interface et un minimum d'implémentation effort forcé sur le programmeur.

La motivation initiale pour introduire des méthodes default à Java 8 était le désir d'étendre les interfaces de Framework Framework avec des méthodes orientées lambda sans rompre aucune implémentation existante. Bien que cela soit plus pertinent pour les auteurs de bibliothèques publiques, vous pouvez également trouver la même fonctionnalité utile dans votre projet. Vous disposez d'un emplacement centralisé pour ajouter de nouvelles fonctionnalités et vous n'avez pas à vous fier à l'apparence du reste de la hiérarchie des types.

246
Marko Topolnik

Il y a quelques différences techniques. Les classes abstraites peuvent encore faire plus par rapport aux interfaces Java 8:

  1. La classe abstraite peut avoir un constructeur.
  2. Les classes abstraites sont plus structurées et peuvent contenir un état.

Sur le plan conceptuel, l'objectif principal des méthodes defender est la compatibilité avec les versions antérieures après l'introduction de nouvelles fonctionnalités (comme les fonctions lambda) dans Java 8.

96
Vadym Vasyliev

Ceci est décrit dans cet article article . Pensez à forEach de collections.

List<?> list = …
list.forEach(…);

Le forEach n'est pas déclaré par Java.util.List ni le Java.util.Collection interface pour le moment. Une solution évidente serait de ajoutez simplement la nouvelle méthode à l'interface existante et fournissez le fichier mise en œuvre si nécessaire dans le JDK. Cependant, une fois publié, il est impossible d'ajouter des méthodes à une interface sans casser le mise en œuvre existante.

L’avantage des méthodes par défaut est qu’il est maintenant possible de ajoutez une nouvelle méthode par défaut à l’interface et cela ne cassera pas le .__ mises en œuvre.

58
Masudul

Comme décrit dans this article,

Classes abstraites versus interfaces en Java 8

Après avoir introduit Default Method, il semble que les interfaces et les classes abstraites sont les mêmes. Cependant, ils sont toujours un concept différent en Java 8.

La classe abstraite peut définir un constructeur. Ils sont plus structurés et peut avoir un état qui leur est associé. En revanche, par défaut Cette méthode ne peut être implémentée qu’en invoquant une autre méthodes d'interface, sans référence à une implémentation particulière Etat. Par conséquent, les deux utilisent à des fins différentes et en choisissant entre deux dépend vraiment du contexte du scénario.

15
Sufiyan Ghori

Ces deux sont très différents:

Les méthodes par défaut consistent à ajouter une fonctionnalité externe aux classes existantes sans modifier leur état.

Et les classes abstraites sont un type d'héritage normal, ce sont des classes normales qui doivent être étendues.

14
Andrey Chaschev

Concernant votre question de 

Alors, quand faut-il utiliser l'interface avec les méthodes par défaut et quand utiliser une classe abstraite? Les classes abstraites sont-elles toujours utiles dans ce scénario?

Java documentation fournit une réponse parfaite. 

Classes abstraites comparées aux interfaces:

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.

Les cas d'utilisation de chacun d'entre eux ont été expliqués ci-dessous, poste SE:

Quelle est la différence entre une classe d'interface et abstraite?

Les classes abstraites sont-elles toujours utiles dans ce scénario?

Oui. Ils sont toujours utiles. Ils peuvent contenir des méthodes non statiques non finales et des attributs (protégés, privés en plus des publics), ce qui n'est pas possible même avec les interfaces Java-8. 

12
Ravindra babu

Chaque fois que nous avons le choix entre une classe abstraite et une interface, nous devrions toujours (presque) préférer les méthodes par défaut (également appelées extensions de défenseur ou virtuelles).

  1. Les méthodes par défaut ont mis fin au modèle d'interface classique et à une classe d'accompagnement qui implémente la plupart ou la totalité des méthodes de cette interface. Un exemple est Collection and AbstractCollection. Nous devons maintenant implémenter les méthodes dans l'interface elle-même pour fournir une fonctionnalité par défaut. Les classes qui implémentent l'interface ont le choix de remplacer les méthodes ou d'hériter de l'implémentation par défaut.
  2. Une autre utilisation importante des méthodes par défaut est interface evolution. Supposons que j'ai un ballon de classe comme:

    public class Ball implements Collection { ... }

Maintenant, dans Java 8, une nouvelle fonctionnalité est introduite. Nous pouvons obtenir un flux en utilisant la méthode stream ajoutée à l'interface. Si stream n'était pas une méthode par défaut, toutes les implémentations de l'interface Collection se seraient rompues car elles ne mettraient pas en œuvre cette nouvelle méthode. L'ajout d'une méthode autre que celle par défaut à une interface n'est pas source-compatible.

Mais supposons que nous ne recompilons pas la classe et utilisons un ancien fichier jar contenant cette classe Ball. La classe se chargera bien sans cette méthode manquante, des instances peuvent être créées et il semble que tout fonctionne correctement.MAISsi le programme appelle la méthode stream sur une instance de Ball, nous obtiendrons AbstractMethodError. La méthode par défaut a donc résolu les deux problèmes.

11
i_am_zero

Les méthodes par défaut dans l'interface Java permettent interface evolution.

Si vous souhaitez ajouter une méthode à une interface existante sans rompre la compatibilité binaire avec les anciennes versions de l'interface, vous avez deux options: ajouter une méthode par défaut ou statique. En effet, toute méthode abstraite ajoutée à l'interface devrait être implémentée par les classes ou les interfaces implémentant cette interface.

Une méthode statique est unique à une classe. Une méthode par défaut est unique à une instance de la classe.

Si vous ajoutez une méthode par défaut à une interface existante, les classes et les interfaces implémentant cette interface n'ont pas besoin de l'implémenter. Ils peuvent

  • implémente la méthode par défaut et remplace l'implémentation dans l'interface implémentée.
  • re-déclarer la méthode (sans implémentation) ce qui la rend abstraite.
  • ne rien faire (la méthode par défaut de l'interface implémentée est simplement héritée).

Plus sur le sujet ici .

6
octoback

quand faut-il utiliser les méthodes par défaut et quand un classe abstraite être utilisé?

Compatibilité ascendante: Imaginez que votre interface soit implémentée par des centaines de classes, sa modification obligera tous les utilisateurs à implémenter la méthode nouvellement ajoutée, même si cela n’est pas indispensable pour de nombreuses autres interface, plus il permet à votre interface d'être une interface fonctionnelle

Faits et restrictions:  

1-Peut uniquement être déclaré dans une interface et non dans une classe ou une classe abstraite

2-Doit fournir un corps

3-Il n'est pas supposé être abstrait comme les autres méthodes normales utilisées dans une interface.

1
Ahmad Sanie

En Java 8, une interface ressemble à une classe abstraite, bien qu'il puisse y avoir quelques différences, telles que:

1) Les classes abstraites sont des classes, elles ne sont donc pas limitées à d'autres restrictions de l'interface en Java, par exemple. La classe abstraite peut avoir l'état , mais vous ne pouvez pas avoir l'état sur l'interface en Java.

2) Une autre différence sémantique entre l'interface avec les méthodes par défaut et la classe abstraite est que vous pouvez définir des constructeurs à l'intérieur d'une classe abstraite , mais vous ne pouvez pas définir un constructeur à l'intérieur de l'interface en Java.

0
Manish Sahni

Comme mentionné dans d'autres réponses, la possibilité d'ajouter une implémentation à une interface a été ajoutée afin d'assurer la compatibilité avec les versions antérieures du framework Collections. Je dirais que la compatibilité ascendante est potentiellement la seule bonne raison d’ajouter une implémentation à une interface.

Sinon, si vous ajoutez l'implémentation à une interface, vous enfreignez la loi fondamentale pour laquelle les interfaces ont été ajoutées en premier lieu. Java est un langage à héritage unique, contrairement au C++ qui permet pour héritage multiple. Les interfaces offrent les avantages de typage fournis avec un langage prenant en charge l'héritage multiple sans introduire les problèmes liés à l'héritage multiple.

Plus spécifiquement, Java n'autorise l'héritage qu'une implémentation, mais autorise l'héritage de plusieurs interfaces. Par exemple, ce qui suit est un code Java valide:

class MyObject extends String implements Runnable, Comparable { ... }

MyObject hérite d'une seule implémentation, mais de trois contrats.

Java a transmis plusieurs héritages d'implémentation, car plusieurs héritages d'implémentation sont livrés avec une foule de problèmes épineux, qui sortent du cadre de cette réponse. Des interfaces ont été ajoutées pour permettre l'héritage multiple de contrats (également appelé interfaces) sans les problèmes d'héritage multiple d'implémentation.

Pour appuyer mon propos, voici une citation de Ken Arnold et James Gosling tirée du livre . Le Java Langage de programmation, 4ème édition :

L'héritage unique exclut certaines conceptions utiles et correctes. Les problèmes d'héritage multiple proviennent d'un héritage multiple d'implémentation, mais dans de nombreux cas, l'héritage multiple est utilisé pour hériter d'un certain nombre de contrats abstraits et peut-être d'une implémentation concrète. Fournir un moyen d'hériter d'un contrat abstrait sans hériter d'une implémentation permet de profiter des avantages de typage d'un héritage multiple sans les problèmes d'héritage de plusieurs implémentations. L'héritage d'un contrat abstrait est appelé héritage d'interface . Le langage de programmation Java prend en charge l'héritage d'interface en vous permettant de déclarer un type interface.

0
johnnyodonnell

S'il vous plaît pensez d'abord au principe d'ouverture/fermeture. Les méthodes par défaut des interfaces le VIOLATENT. C'est une mauvaise fonctionnalité en Java. Cela encourage une mauvaise conception, une mauvaise architecture et une qualité logicielle médiocre. Je suggère d'éviter d'utiliser complètement les méthodes par défaut.

Posez-vous quelques questions: Pourquoi ne pouvez-vous pas mettre vos méthodes en classe abstraite? Auriez-vous besoin de plus d'une classe abstraite? Ensuite, réfléchissez à ce que votre classe est responsable de. Etes-vous sûr que toutes les méthodes que vous allez mettre dans la même classe remplissent vraiment le même objectif? Peut-être distinguerez-vous plusieurs objectifs et diviserez ensuite votre classe en plusieurs classes, chacune ayant sa propre classe.

0
mentallurg

Les méthodes par défaut dans l'interface Java doivent être davantage utilisées pour fournir une implémentation fictive d'une fonction, ce qui évite à toute classe d'implémentation de cette interface de déclarer toutes les méthodes abstraites, même si elles ne veulent traiter qu'une seule .. interface sont donc en quelque sorte un remplacement du concept de classe d’adaptateur.

Les méthodes de la classe abstraite sont toutefois supposées donner une implémentation significative que toute classe enfant ne doit remplacer que si cela est nécessaire pour remplacer une fonctionnalité commune.

0
shubh