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.
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
0 votes
Vous pouvez parfois coder une classe de base comme une interface même si la classe de base a un état. C'est juste que l'interface doit définir des setters et des getters pour l'état et que les classes concrètes doivent les implémenter et définir le champ. Une restriction à ce sujet est que dans une classe abstraite, la propriété du bean peut être privée ou protégée. Dans les interfaces, les méthodes ne sont que publiques. Ainsi, l'une des raisons pour lesquelles vous utilisez une classe de base abstraite est que vos classes ont une propriété qui doit être privée ou protégée.
0 votes
@DaBlick Ne pourriez-vous pas résoudre le problème d'état dans une interface via un HashMap. Ex : si vous voulez une classe Foo qui contient int a, b, String c. et vous voulez qu'ils aient un état, créez un HashMap< /*nom de l'objet Foo*/ String, /*map des champs*/ Hashmap< /*nom du champ spécifique*/ String, /*valeur du champ*/ Object>> map. Lorsque vous voulez "instancier" la classe théorique Foo, vous avez la méthode, instantiate(String nameOfFoo) qui fait map.put(nameOfFoo, fields) où fields est un HashMap<String, Object> fields.put("a", new int("5")) ; fields.put("b", new int("6")) ; fields.put("c", "blah")) ;
0 votes
Autrement dit <"nameOfFoo", <"specificfieldofFoo", fieldValue> >
0 votes
@GeorgeXavier Pour moi, il me semble que le HashMap dont vous parlez EST un "état". Je ne pense pas que dans une interface, vous ayez un moyen de conserver l'"état" de la table de hachage.
0 votes
@DaBlick une carte ou une collection finale statique peut contenir des valeurs non statiques... Je pense. Dans ce cas, la carte lie le nom de l'objet à une autre carte qui lie le champ spécifique dans l'objet spécifique, à la valeur. Comme un index. Entrez le nom de l'"instance" qui récupère la carte des champs. Saisissez le nom du champ spécifique dans cette "instance" déjà récupérée, afin de récupérer la valeur du champ.
0 votes
@GeorgeXavier Ce n'est pas sémantiquement équivalent aux champs en général. Seulement aux champs statiques. Je considérerais cela comme une mauvaise pratique et je découragerais cela. Toutes les implémentations de l'interface partageraient les mêmes valeurs de propriété (comme les champs statiques, mais contrairement aux champs non statiques). Vous vous exposez également à des bogues, à des problèmes de ré-entrance, etc. JMHO
0 votes
@DaBlick Ce n'est pas un champ, mais il fonctionne comme un équivalent. Tout ce que vous faites est de lier l'objet à un nom via une chaîne et un hashmap, et les équivalents "champ" seraient à l'intérieur du second hashmap. Je n'ai jamais voulu dire que systématiquement, c'est un champ. Je voulais plutôt dire que cela fonctionne comme un équivalent dans la mesure où cela permettra techniquement une "instanciation" simulée. Je ne sais pas ce que vous entendez par valeurs de propriété ; les valeurs à l'intérieur du hashmap peuvent être modifiées même si le hashmap en lui-même est statique. Par contre, je ne sais pas ce qu'est la ré-entrée.
0 votes
Les méthodes par défaut ont mis un terme au schéma classique : stackoverflow.com/a/32774868/1216775