Java 8 a inclus une nouvelle fonctionnalité appelée Méthodes Defender qui permet la création d’une implémentation de méthode par défaut dans l’interface.
Tout d’abord, c’est un énorme changement de paradigme pour tous les programmeurs condensés en Java. J'ai consulté une présentation de JavaOne 13 donnée par Brain Goetz dans laquelle il discutait des nouvelles implémentations de stream()
et parallelStream()
dans la bibliothèque de collections.
Pour ajouter de nouvelles méthodes dans l'interface Collection
, ils n'auraient pas pu ajouter une nouvelle méthode sans rompre les versions précédentes. Il a donc ajouté qu'une nouvelle fonctionnalité des méthodes par défaut avait été ajoutée.
public interface SimpleInterface {
public void doSomeWork();
//A default method in the interface created using "default" keyword
default public void doSomeOtherWork(){
System.out.println("DoSomeOtherWork implementation in the interface");
}
}
Maintenant, ma question est la suivante: les méthodes par défaut sont-elles simplement utiles lorsque cela est nécessaire pour ajouter de nouvelles méthodes à l'interface sans casser le code client? Ou y a-t-il d'autres utilisations?
En plus d'avoir la possibilité d'ajouter des méthodes à l'interface dans les versions futures, il est important de permettre à une variable interface
de rester une interface fonctionnelle même si elle comporte plusieurs méthodes.
Une interface fonctionnelle ne possède qu'une seule méthode abstraite autre que celle par défaut pouvant être implémentée via une expression lambda. Un exemple est l'interface Predicate
qui n'a qu'une seule méthode abstraite (test
) tout en fournissant des méthodes par défaut pour nier une Predicate
ou la combiner avec une autre Predicate
. Sans méthodes par défaut, ces méthodes devaient être fournies dans une autre classe d’utilitaires telle que la classe Collections
antérieure à Java 8 (vous ne voulez pas renoncer à la possibilité d’une implémentation lambda pour une telle variable interface
).
Comme vous l'avez dit, la motivation principale permettait l'évolution des interfaces existantes.
Cependant il y a des raisons pour lesquelles vous voudriez également les utiliser dans de toutes nouvelles interfaces:
L'une de ces raisons concerne les méthodes qui peuvent facilement être implémentées à l'aide des autres méthodes (autres que celles par défaut) de l'interface. L'utilisation de méthodes default
pour cela réduit la nécessité de combinaisons Foo
- interface/AbstractFoo
- base-implémentation (voir AbstractList
pour un exemple).
Bien que cela ne crée pas un champ entièrement nouveau, cela signifie que vous pouvez avoir des interfaces conviviales pour les utilisateurs finaux (avec de nombreuses méthodes utiles), tout en conservant une mise en œuvre simple.
Il y avait un problème avec les interfaces parce qu'elles n'étaient pas ouvertes à l'extension, ce qui signifie que s'il était nécessaire d'ajouter une nouvelle méthode à une interface, cela aurait cassé l'implémentation existante de ces interfaces. Il était donc impératif que toutes les classes implémentant cette interface devaient fournir l'implémentation de la méthode nouvellement ajoutée, même si la méthode n'était pas nécessaire. Ainsi, les interfaces n'étaient pas faciles à faire évoluer.
Un exemple qui me vient à l’esprit est l’API Java MapReduce pour Hadoop, qui a été modifiée dans la version 0.20.0 pour favoriser les classes abstraites par rapport aux interfaces, car elles sont plus faciles à faire évoluer. Ce qui signifie qu’une nouvelle méthode peut être ajoutée à la classe abstraite (avec une implémentation par défaut), en évitant les anciennes implémentations de la classe.
Avec la sortie de Java 8, il est maintenant possible d’ajouter une méthode par défaut aux interfaces, ce qui les rend plus faciles à faire évoluer. Avec l'ajout d'une méthode par défaut à une interface, l'ajout d'une nouvelle méthode à une interface ne rompt pas le code préexistant.