Java 8 permet l'implémentation par défaut des méthodes dans les interfaces appelées méthodes par défaut .
Je suis confus entre quand utiliserais-je ce genre de interface default method
, au lieu d'un abstract class
(avec abstract method(s)
).
Alors, quand utiliser l'interface avec les méthodes par défaut et quand utiliser une classe abstraite (avec des méthodes abstraites)? Les classes abstraites sont-elles toujours utiles dans ce scénario?
java
interface
java-8
abstract-class
default-method
Narendra Pathai
la source
la source
Réponses:
Les classes abstraites ont bien plus à offrir que les implémentations de méthodes par défaut (comme l'état privé), mais à partir de Java 8, chaque fois que vous avez le choix, vous devez utiliser la
default
méthode defender (aka. ) Dans l'interface.La contrainte de 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 cas d'utilisation principal est donc les méthodes de niveau supérieur et de commodité.
La bonne chose à propos de cette nouvelle fonctionnalité est que, où 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'implémentation effort imposé au programmeur.
La motivation initiale pour introduire des
default
méthodes dans Java 8 était le désir d'étendre les interfaces Collections Framework avec des méthodes orientées lambda sans casser aucune implémentation existante. Bien que cela soit plus pertinent pour les auteurs des 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 de types.la source
Il existe quelques différences techniques. Les classes abstraites peuvent encore faire plus par rapport aux interfaces Java 8:
Sur le plan conceptuel, l'objectif principal des méthodes de défense est une compatibilité descendante après l'introduction de nouvelles fonctionnalités (comme les fonctions lambda) dans Java 8.
la source
public static final
champs d'une interface comme "état". Lastatic
partie signifie que vous n'êtes pas du tout lié à une instance particulière. Ils sont attribués lors de l'instanciation de classe , ce qui n'est pas la même chose qu'après la création d'une instance .Cela est décrit dans cet article . Pensez aux
forEach
collections.la source
AbstractList::forEach
lancer unUnsupportedOperationException
.Ces deux sont assez différents:
Les méthodes par défaut consistent à ajouter des fonctionnalités externes aux classes existantes sans modifier leur état.
Et les classes abstraites sont un type d'héritage normal, ce sont des classes normales qui sont destinées à être étendues.
la source
Comme décrit dans cet article,
Classes abstraites et interfaces dans Java 8
la source
Concernant votre requête de
la documentation java fournit une réponse parfaite.
Classes abstraites comparées aux interfaces:
Les cas d'utilisation pour chacun d'entre eux ont été expliqués dans le post SE ci-dessous:
Quelle est la différence entre une interface et une classe abstraite?
Oui. Ils sont toujours utiles. Ils peuvent contenir des méthodes et des attributs non statiques et non finaux ( protégés, privés en plus du public ), ce qui n'est pas possible même avec les interfaces Java-8.
la source
Chaque fois que nous avons le choix entre la classe abstraite et l'interface, nous devrions toujours (presque) préférer les méthodes par défaut (également appelées défenseur ou extensions virtuelles).
Collection and AbstractCollection
. Maintenant, nous devons implémenter les méthodes dans l'interface elle-même pour fournir des fonctionnalités 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.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é est introduite. Nous pouvons obtenir un flux en utilisant une
stream
méthode ajoutée à l'interface. Si cestream
n'était pas une méthode par défaut, toutes les implémentations de l'Collection
interface se seraient rompues car elles ne mettraient pas en œuvre cette nouvelle méthode. L'ajout d'une méthode non par défaut à une interface ne l'est passource-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 chargera correctement sans cette méthode manquante, des instances peuvent être créées et il semble que tout fonctionne correctement. MAIS si le programme invoque lastream
méthode sur l'instance deBall
we obtiendraAbstractMethodError
. Donc, la méthode par défaut a résolu les deux problèmes.la source
Les méthodes par défaut dans l'interface Java permettent l' évolution de l'interface .
Étant donné une interface existante, si vous souhaitez y ajouter une méthode sans rompre la compatibilité binaire avec les anciennes versions de l'interface, vous avez deux options: ajouter une méthode par défaut ou une méthode statique. En effet, toute méthode abstraite ajoutée à l'interface devrait être implémentée par les classes ou 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 interfaces qui implémentent cette interface n'ont pas besoin de l'implémenter. Ils peuvent
Plus d'informations sur le sujet ici .
la source
Bien que ce soit une vieille question, permettez-moi également de vous faire part de mes commentaires.
classe abstraite: à l' intérieur de la classe abstraite, nous pouvons déclarer des variables d'instance, qui sont obligatoires pour la classe enfant
Interface: à l' intérieur de l'interface, toutes les variables sont toujours statiques publiques et nous ne pouvons pas déclarer de variables d'instance
classe abstraite: la classe abstraite peut parler de l'état de l'objet
Interface: l' interface ne peut jamais parler de l'état de l'objet
classe abstraite: à l' intérieur de la classe abstraite, nous pouvons déclarer des constructeurs
Interface: à l' intérieur de l'interface, nous ne pouvons pas déclarer les constructeurs
constructeurs est d'initialiser des variables d'instance. Alors, quel est le besoin de constructeur là-bas si nous ne pouvons pas avoir de variables d'instance dans les interfaces .
classe abstraite: à l' intérieur de la classe abstraite, nous pouvons déclarer des blocs d'instance et statiques
Interface: interfaces ne peuvent pas avoir d'instance et de blocs statiques.
classe abstraite: abstraite ne peut pas faire référence à l'expression lambda
Interfaces: interfaces avec une seule méthode abstraite peuvent faire référence à l'expression lambda
classe abstraite : à l'intérieur de la classe abstraite, nous pouvons remplacer les méthodes OBJECT CLASS
Interfaces: nous ne pouvons pas remplacer les méthodes OBJECT CLASS dans les interfaces.
Je terminerai sur la note que:
Les concepts de méthode par défaut / concepts de méthode statique dans l'interface sont venus juste pour enregistrer les classes d'implémentation mais pas pour fournir une implémentation utile significative. Les méthodes par défaut / méthodes statiques sont une sorte d'implémentation factice, "si vous le souhaitez, vous pouvez les utiliser ou vous pouvez les remplacer (dans le cas des méthodes par défaut) dans la classe d'implémentation", ce qui nous évite d'implémenter de nouvelles méthodes dans les classes d'implémentation chaque fois que de nouvelles méthodes dans les interfaces sont ajoutés. Par conséquent, les interfaces ne peuvent jamais être égales à des classes abstraites.
la source
La règle de Remi Forax est Vous ne concevez pas avec des classes abstraites. Vous concevez votre application avec des interfaces . Watever est la version de Java, quel que soit le langage. Il est soutenu par le I principe de ségrégation nterface en SOL I D principes.
Vous pouvez ultérieurement utiliser des classes abstraites pour factoriser le code. Maintenant, avec Java 8, vous pouvez le faire directement dans l'interface. C'est une installation, pas plus.
la source
Compatibilité descendante: imaginez que votre interface est implémentée par des centaines de classes, la modification de cette interface forcera tous les utilisateurs à implémenter la méthode nouvellement ajoutée, même si cela pourrait ne pas être essentiel pour de nombreuses autres classes qui implémentent votre interface, en plus cela permet à votre interface être une interface fonctionnelle
Faits et restrictions:
1-Ne peut être déclaré que 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.
la source
Dans Java 8, une interface ressemble à une classe abstraite, bien qu'il puisse y avoir des 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 dans une classe abstraite , mais vous ne pouvez pas définir d'interface constructeur dans Java
la source
Les méthodes par défaut dans l'interface Java doivent être utilisées davantage pour fournir une implémentation factice d'une fonction, ce qui évite à toute classe d'implémentation de cette interface de devoir déclarer toutes les méthodes abstraites même si elles ne souhaitent en traiter qu'une seule. Les méthodes par défaut dans l'interface remplacent donc en quelque sorte davantage le concept de classes d'adaptateurs.
Les méthodes de la classe abstraite sont cependant censées donner une implémentation significative que toute classe enfant ne doit remplacer que si elle est nécessaire pour remplacer une fonctionnalité commune.
la source
Comme mentionné dans d'autres réponses, la possibilité d'ajouter l'implémentation à une interface a été ajoutée afin de fournir une compatibilité descendante dans le cadre des collections. Je dirais que fournir une compatibilité descendante est potentiellement la seule bonne raison pour ajouter une implémentation à une interface.
Sinon, si vous ajoutez une implémentation à une interface, vous enfreignez la loi fondamentale expliquant pourquoi les interfaces ont été ajoutées en premier lieu. Java est un langage d'héritage unique, contrairement au C ++ qui permet l'héritage multiple. Les interfaces offrent les avantages de frappe qui viennent avec un langage qui prend en charge l'héritage multiple sans introduire les problèmes qui viennent avec l'héritage multiple.
Plus précisément, Java n'autorise que l'héritage unique d'une implémentation, mais il autorise l'héritage multiple d'interfaces. Par exemple, ce qui suit est un code Java valide:
MyObject
hérite d'une seule implémentation, mais hérite de trois contrats.Java a transmis l'héritage multiple de l'implémentation car l'héritage multiple de l'implémentation s'accompagne d'une multitude de problèmes épineux, qui sortent du cadre de cette réponse. Des interfaces ont été ajoutées pour permettre l'héritage multiple des contrats (aka 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 du livre The Java Programming Language, 4e édition :
la source
Veuillez d'abord penser au principe ouvert / fermé. Les méthodes par défaut dans les interfaces le VIOLENT. C'est une mauvaise fonctionnalité en Java. Il encourage une mauvaise conception, une mauvaise architecture, une faible qualité logicielle. Je suggérerais 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 dans la classe abstraite? Auriez-vous besoin de plus d'une classe abstraite? Réfléchissez ensuite aux responsabilités de votre classe. Êtes-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 que vous distinguerez plusieurs objectifs et diviserez ensuite votre classe en plusieurs classes, pour chaque objectif sa propre classe.
la source