Différence entre la classe Abstact et l'interface
- Classes abstraites et interfaces dans Java 8
- Différence conceptuelle:
Méthodes par défaut de l'interface dans Java 8
- Qu'est-ce que la méthode par défaut?
- Erreur de compilation de la méthode ForEach résolue à l'aide de la méthode par défaut
- Méthode par défaut et problèmes d'ambiguïté d'héritage multiples
- Points importants sur les méthodes par défaut de l'interface java:
Méthode statique de l'interface Java
- Java Interface Static Method, exemple de code, méthode statique vs méthode par défaut
- Points importants sur la méthode statique de l'interface java:
Interfaces fonctionnelles Java
Classes abstraites et interfaces dans Java 8
Les changements d'interface Java 8 incluent des méthodes statiques et des méthodes par défaut dans les interfaces. Avant Java 8, nous ne pouvions avoir que des déclarations de méthode dans les interfaces. Mais à partir de Java 8, nous pouvons avoir des méthodes par défaut et des méthodes statiques dans les interfaces.
Après avoir introduit la méthode par défaut, il semble que les interfaces et les classes abstraites soient identiques. Cependant, ils sont encore différents concept dans Java 8.
La classe abstraite peut définir le constructeur. Ils sont plus structurés et peuvent avoir un état qui leur est associé. En revanche, 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 à l'état d'une implémentation particulière. Par conséquent, les deux utilisations à des fins différentes et le choix entre deux dépendent vraiment du contexte du scénario.
Différence conceptuelle:
Les classes abstraites sont valables pour les implémentations squelettiques (c'est-à-dire partielles) des interfaces mais ne devraient pas exister sans interface correspondante.
Ainsi, lorsque les classes abstraites sont effectivement réduites pour être des implémentations squelettiques d'interfaces à faible visibilité, les méthodes par défaut peuvent-elles également supprimer cela? Décidément: Non! L'implémentation d'interfaces nécessite presque toujours une partie ou la totalité de ces outils de création de classe qui manquent aux méthodes par défaut. Et si une interface ne fonctionne pas, c'est clairement un cas spécial, qui ne devrait pas vous induire en erreur.
Méthodes par défaut de l'interface dans Java 8
Java 8 présente la « méthode par défaut » ou (méthodes Defender), qui permet au développeur d'ajouter de nouvelles méthodes aux interfaces sans interrompre l'implémentation existante de ces interfaces. Il offre une flexibilité permettant à l'interface de définir l'implémentation qui sera utilisée par défaut dans le cas où une classe concrète ne fournira pas d'implémentation pour cette méthode.
Prenons un petit exemple pour comprendre comment cela fonctionne:
public interface OldInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method"
+ " is added in interface");
}
}
La classe suivante se compilera avec succès dans Java JDK 8,
public class OldInterfaceImpl implements OldInterface {
public void existingMethod() {
// existing implementation is here…
}
}
Si vous créez une instance de OldInterfaceImpl:
OldInterfaceImpl obj = new OldInterfaceImpl ();
// print “New default method add in interface”
obj.newDefaultMethod();
Les méthodes par défaut ne sont jamais définitives, ne peuvent pas être synchronisées et ne peuvent pas remplacer les méthodes d'Object. Ils sont toujours publics, ce qui limite considérablement la possibilité d'écrire des méthodes courtes et réutilisables.
Des méthodes par défaut peuvent être fournies à une interface sans affecter les classes d'implémentation car elle inclut une implémentation. Si chaque méthode ajoutée dans une interface définie avec implémentation, aucune classe d'implémentation n'est affectée. Une classe d'implémentation peut remplacer l'implémentation par défaut fournie par l'interface.
Les méthodes par défaut permettent d'ajouter de nouvelles fonctionnalités aux interfaces existantes sans rompre la mise en œuvre plus ancienne de ces interfaces.
Lorsque nous étendons une interface qui contient une méthode par défaut, nous pouvons effectuer ce qui suit,
- Ne pas remplacer la méthode par défaut et héritera de la méthode par défaut.
- Remplacez la méthode par défaut similaire aux autres méthodes que nous substituons dans la sous-classe.
- Redéclarez la méthode par défaut comme abstraite, ce qui force la sous-classe à la remplacer.
Erreur de compilation de la méthode ForEach résolue à l'aide de la méthode par défaut
Pour Java 8, les collections JDK ont été étendues et la méthode forEach est ajoutée à la collection entière (qui fonctionne en conjonction avec lambdas). De manière conventionnelle, le code ressemble à ci-dessous,
public interface Iterable<T> {
public void forEach(Consumer<? super T> consumer);
}
Étant donné que cela entraîne chaque classe d'implémentation avec des erreurs de compilation par conséquent, une méthode par défaut a été ajoutée avec une implémentation requise afin que l'implémentation existante ne soit pas modifiée.
L'interface itérable avec la méthode par défaut est ci-dessous,
public interface Iterable<T> {
public default void forEach(Consumer
<? super T> consumer) {
for (T t : this) {
consumer.accept(t);
}
}
}
Le même mécanisme a été utilisé pour ajouter Stream dans l'interface JDK sans rompre les classes d'implémentation.
Méthode par défaut et problèmes d'ambiguïté d'héritage multiples
Étant donné que java Class peut implémenter plusieurs interfaces et que chaque interface peut définir une méthode par défaut avec la même signature de méthode, les méthodes héritées peuvent donc entrer en conflit les unes avec les autres.
Considérez l'exemple ci-dessous,
public interface InterfaceA {
default void defaultMethod(){
System.out.println("Interface A default method");
}
}
public interface InterfaceB {
default void defaultMethod(){
System.out.println("Interface B default method");
}
}
public class Impl implements InterfaceA, InterfaceB {
}
Le code ci-dessus ne parviendra pas à compiler avec l'erreur suivante,
java: la classe Impl hérite des valeurs par défaut non liées pour defaultMethod () des types InterfaceA et InterfaceB
Afin de corriger cette classe, nous devons fournir une implémentation de méthode par défaut:
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
}
}
De plus, si nous voulons invoquer l'implémentation par défaut fournie par l'une des super interfaces plutôt que notre propre implémentation, nous pouvons le faire comme suit,
public class Impl implements InterfaceA, InterfaceB {
public void defaultMethod(){
// existing code here..
InterfaceA.super.defaultMethod();
}
}
Nous pouvons choisir n'importe quelle implémentation par défaut ou les deux dans le cadre de notre nouvelle méthode.
Points importants sur les méthodes par défaut de l'interface java:
- Les méthodes par défaut des interfaces Java nous aideront à étendre les interfaces sans avoir peur de casser les classes d'implémentation.
- Les méthodes par défaut de l'interface Java ont permis de réduire les différences entre les interfaces et les classes abstraites.
- Les méthodes par défaut de l'interface Java 8 nous aideront à éviter les classes utilitaires, telles que toutes les méthodes de la classe Collections peuvent être fournies dans les interfaces elles-mêmes.
- Les méthodes par défaut de l'interface Java nous aideront à supprimer les classes d'implémentation de base, nous pouvons fournir l'implémentation par défaut et les classes d'implémentation peuvent choisir celle à remplacer.
- L'une des principales raisons de l'introduction de méthodes par défaut dans les interfaces est d'améliorer l'API Collections en Java 8 pour prendre en charge les expressions lambda.
- Si une classe de la hiérarchie a une méthode avec la même signature, alors les méthodes par défaut deviennent inutiles. Une méthode par défaut ne peut pas remplacer une méthode de java.lang.Object. Le raisonnement est très simple, c'est parce que Object est la classe de base pour toutes les classes java. Donc, même si nous avons des méthodes de classe Object définies comme méthodes par défaut dans les interfaces, cela sera inutile car la méthode de classe Object sera toujours utilisée. C'est pourquoi, pour éviter toute confusion, nous ne pouvons pas avoir de méthodes par défaut qui remplacent les méthodes de classe Object.
- Les méthodes par défaut de l'interface Java sont également appelées méthodes Defender ou méthodes d'extension virtuelle.
Lien de ressource:
- Interface avec les méthodes par défaut vs classe abstraite en Java 8
- Classe abstraite versus interface à l'ère JDK 8
- Evolution de l'interface via des méthodes d'extension virtuelle
Méthode statique de l'interface Java
Java Interface Static Method, exemple de code, méthode statique vs méthode par défaut
La méthode statique de l'interface Java est similaire à la méthode par défaut, sauf que nous ne pouvons pas les remplacer dans les classes d'implémentation. Cette fonctionnalité nous aide à éviter les résultats indésirables en cas de mauvaise implémentation dans les classes d'implémentation. Examinons cela avec un exemple simple.
public interface MyData {
default void print(String str) {
if (!isNull(str))
System.out.println("MyData Print::" + str);
}
static boolean isNull(String str) {
System.out.println("Interface Null Check");
return str == null ? true : "".equals(str) ? true : false;
}
}
Voyons maintenant une classe d'implémentation qui a la méthode isNull () avec une mauvaise implémentation.
public class MyDataImpl implements MyData {
public boolean isNull(String str) {
System.out.println("Impl Null Check");
return str == null ? true : false;
}
public static void main(String args[]){
MyDataImpl obj = new MyDataImpl();
obj.print("");
obj.isNull("abc");
}
}
Notez que isNull (String str) est une méthode de classe simple, elle ne remplace pas la méthode d'interface. Par exemple, si nous ajoutons une annotation @Override à la méthode isNull (), cela entraînera une erreur de compilation.
Maintenant, lorsque nous exécuterons l'application, nous obtenons la sortie suivante.
Interface Null Check
Impl Null Check
Si nous faisons la méthode d'interface de statique à par défaut, nous obtiendrons la sortie suivante.
Impl Null Check
Impression MyData ::
Impl Null Check
La méthode statique d'interface Java n'est visible que pour les méthodes d'interface, si nous supprimons la méthode isNull () de la classe MyDataImpl, nous ne pourrons pas l'utiliser pour l'objet MyDataImpl. Cependant, comme d'autres méthodes statiques, nous pouvons utiliser des méthodes statiques d'interface en utilisant le nom de classe. Par exemple, une déclaration valide sera:
boolean result = MyData.isNull("abc");
Points importants sur la méthode statique de l'interface java:
- La méthode statique de l'interface Java fait partie de l'interface, nous ne pouvons pas l'utiliser pour les objets de classe d'implémentation.
- Les méthodes statiques de l'interface Java sont utiles pour fournir des méthodes utilitaires, par exemple la vérification nulle, le tri de collection, etc.
- La méthode statique de l'interface Java nous aide à assurer la sécurité en ne permettant pas aux classes d'implémentation de les remplacer.
- Nous ne pouvons pas définir de méthode statique d'interface pour les méthodes de classe Object, nous obtiendrons une erreur de compilation comme «Cette méthode statique ne peut pas cacher la méthode d'instance d'Object». C'est parce que ce n'est pas autorisé en java, car Object est la classe de base pour toutes les classes et nous ne pouvons pas avoir une méthode statique au niveau de la classe et une autre méthode d'instance avec la même signature.
- Nous pouvons utiliser des méthodes statiques d'interface java pour supprimer des classes utilitaires telles que Collections et déplacer toutes ses méthodes statiques vers l'interface correspondante, ce qui serait facile à trouver et à utiliser.
Interfaces fonctionnelles Java
Avant de conclure le message, je voudrais fournir une brève introduction aux interfaces fonctionnelles. Une interface avec exactement une méthode abstraite est connue sous le nom d'interface fonctionnelle.
Une nouvelle annotation @FunctionalInterface
a été introduite pour marquer une interface comme interface fonctionnelle.@FunctionalInterface
l'annotation est un moyen d'éviter l'ajout accidentel de méthodes abstraites dans les interfaces fonctionnelles. Il est facultatif mais bon de l'utiliser.
Les interfaces fonctionnelles sont une fonctionnalité attendue depuis longtemps et très recherchée de Java 8 car elle nous permet d'utiliser des expressions lambda pour les instancier. Un nouveau package java.util.function avec un tas d'interfaces fonctionnelles est ajouté pour fournir des types cibles pour les expressions lambda et les références de méthode. Nous étudierons les interfaces fonctionnelles et les expressions lambda dans les prochains articles.
Emplacement des ressources:
- Modifications de l'interface Java 8 - méthode statique, méthode par défaut