607 votes

Quand l'utiliser : Méthode par défaut de l'interface Java 8+, vs. méthode abstraite

Java 8 permet l'implémentation par défaut de méthodes dans des interfaces appelées Méthodes par défaut .

Je suis confus entre le moment où j'utiliserais ce genre de interface default method au lieu d'un abstract class (avec abstract method(s) ).

Alors, quand faut-il utiliser une interface avec des méthodes par défaut et quand faut-il utiliser une classe abstraite (avec une ou plusieurs méthodes abstraites) ? Les classes abstraites sont-elles encore utiles dans ce scénario ?

45 votes

Peut-être que vous ne pouvez toujours pas avoir de champs, de méthodes privées, etc. dans les interfaces, alors que vous le pouvez dans les classes abstraites ?

2 votes

Je m'interrogeais sur ce sujet avant, maintenant je suis clair. Merci à @Narendra Pathai . Je voudrais ajouter le lien d'un autre fil de discussion que vous avez demandé concernant le même sujet, car ces deux sujets étaient mes doutes. stackoverflow.com/questions/19998309/

0 votes

Vous pouvez trouver un bon article sur ce sujet ici : blog.codefx.org/java/everything-about-default-methods

355voto

Marko Topolnik Points 77257

Les classes abstraites comportent bien plus que des implémentations de méthodes par défaut (comme l'état privé), mais à partir de Java 8, lorsque vous avez le choix entre les deux, vous devez opter pour le défenseur (alias. default ) de 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 celui des méthodes de niveau supérieur et de commodité.

L'avantage de cette nouvelle fonctionnalité est que, alors qu'auparavant vous étiez obligé d'utiliser une classe abstraite pour les méthodes de commodité, contraignant ainsi l'implémenteur à l'héritage unique, vous pouvez maintenant avoir une conception vraiment propre avec juste l'interface et un minimum d'effort d'implémentation imposé au programmeur.

La motivation initiale de l'introduction de la default Le désir d'étendre les interfaces du Collections Framework avec des méthodes orientées lambda sans rompre les implémentations existantes a été à l'origine de l'introduction des méthodes lambda dans Java 8. Bien que cela soit plus pertinent pour les auteurs de bibliothèques publiques, vous pouvez trouver la même fonctionnalité utile dans votre projet également. Vous disposez d'un endroit centralisé où ajouter de nouvelles commodités et vous ne devez pas dépendre de l'aspect du reste de la hiérarchie des types.

37 votes

Selon ce raisonnement, la prochaine chose qu'ils ajouteraient serait des déclarations de méthodes par défaut. Je ne suis toujours pas sûr de cela, la fonctionnalité me semble plus être un hack qui est exposé à tout le monde pour une mauvaise utilisation.

3 votes

La seule utilisation des classes abstraites dans l'ère Java 8 que je puisse voir est pour définir des champs non finaux. Dans les interfaces, les champs sont par défaut définitifs et vous ne pouvez pas les modifier une fois qu'ils sont attribués.

1 votes

@Anuroop Les interfaces ne peuvent pas du tout déclarer de champs d'instance.

143voto

Vadym Vasyliev Points 56

Il existe quelques différences techniques. Les classes abstraites peuvent toujours faire plus par rapport aux interfaces de Java 8 :

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

D'un point de vue conceptuel, le principal objectif des méthodes défenderesses est la rétrocompatibilité après l'introduction de nouvelles fonctionnalités (comme les fonctions lambda) dans Java 8.

25 votes

Cette réponse est en fait correcte et a du sens surtout "Conceptuellement, le but principal des méthodes défenderesses est une compatibilité descendante".

1 votes

@UnKnown cette page donne plus d'informations : docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

0 votes

@UnKnown, en gros, cela vous permet d'ajouter des méthodes à une interface et les classes qui implémentent cette interface obtiennent automatiquement cette fonctionnalité.

71voto

Masud Points 10542

C'est ce qui est décrit dans ce article . Pensez à forEach des collections.

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

Le forEach n'est pas déclaré par java.util.List ni le java.util.Collection encore une interface. Une solution évidente serait de d'ajouter la nouvelle méthode à l'interface existante et de fournir l'implémentation de la méthode. l'implémentation dans le JDK. Cependant, une fois publiée, il est il est impossible d'ajouter des méthodes à une interface sans casser la implémentation existante.

L'avantage des méthodes par défaut est qu'il est maintenant possible de d'ajouter une nouvelle méthode par défaut à l'interface sans pour autant casser les implémentations.

1 votes

Il est impossible d'ajouter des méthodes à une interface sans casser l'implémentation existante" - n'est-ce pas ?

28 votes

@AndreyChaschev Si vous ajoutez une nouvelle méthode à l'interface, alors tous les implémenteurs doivent implémenter cette nouvelle méthode. Par conséquent, cela casse les implémentations existantes.

4 votes

@MarkoTopolnik merci, ça m'a échappé. Juste pour mentionner qu'il y a un moyen de partiellement éviter cela - en présentant cette méthode dans une implémentation abstraite par défaut. Dans cet exemple, ce serait AbstractList::forEach en lançant un UnsupportedOperationException .

30voto

Sufiyan Ghori Points 497

Comme décrit dans ce article,

Classes abstraites et interfaces en Java 8

Après avoir introduit la méthode par défaut, il semble que les interfaces et les classes abstraites soient les mêmes. classes abstraites sont identiques. Cependant, elles sont toujours un concept différent dans Java 8.

Une classe abstraite peut définir un constructeur. Elles sont plus structurées et peuvent avoir un état qui leur est associé. Alors qu'à l'inverse, la méthode par défaut ne peut être implémentée qu'en termes d'invocation d'autres méthodes d'interface, sans référence à une implémentation particulière de la méthode. méthodes d'interface, sans référence à l'état d'une implémentation particulière. d'une implémentation particulière. Par conséquent, les deux sont utilisés à des fins différentes et le choix entre les deux dépend réellement du contexte du scénario.

21voto

akhil_mittal Points 40

Lorsque 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 connues sous le nom d'extensions défensives ou virtuelles).

  1. Les méthodes par défaut ont mis fin au modèle classique d'interface et de classe d'accompagnement qui implémente la plupart ou toutes les méthodes de cette interface. Un exemple est Collection and AbstractCollection . Maintenant, nous devons 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 surcharger 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'aie une classe Ball comme :

    public class Ball implements Collection { ... }

Maintenant, dans Java 8, une nouvelle fonctionnalité de flux est introduite. Nous pouvons obtenir un flux en utilisant stream ajoutée à l'interface. Si stream n'étaient pas une méthode par défaut, toutes les implémentations pour les Collection aurait été cassée car elle n'aurait pas mis en œuvre cette nouvelle méthode. L'ajout d'une méthode non par défaut à une interface n'est pas source-compatible .

Mais supposons que nous ne recompilions pas la classe et que nous utilisions un ancien fichier jar qui contient cette classe Ball . La classe se charge bien sans cette méthode manquante, des instances peuvent être créées et il semble que tout fonctionne bien. MAIS si le programme invoque stream sur une instance de Ball nous obtiendrons AbstractMethodError . La méthode par défaut a donc résolu les deux problèmes.

Java 9 a même des méthodes privées dans l'interface qui peuvent être utilisées pour encapsuler la logique de code commune qui était utilisée dans les méthodes de l'interface qui fournissaient une implémentation par défaut.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X