web-dev-qa-db-fra.com

Les valeurs par défaut dans JDK 8 sont-elles une forme d'héritage multiple en Java?

Une nouvelle fonctionnalité intégrée à JDK 8 vous permet d’ajouter à une interface existante tout en préservant la compatibilité binaire.

La syntaxe est comme

public interface SomeInterface() {
  void existingInterface();
  void newInterface() default SomeClass.defaultImplementation;
}

Ainsi, pour toutes les implémentations existantes de SomeInterface, lorsqu’elles passent à cette nouvelle version, elles n’ont pas toutes soudainement compilé des erreurs autour de newInterface().

Bien que cela soit intéressant, que se passe-t-il lorsque vous implémentez deux interfaces qui ont toutes deux ajouté une nouvelle méthode par défaut que vous n'avez pas implémentée? Laissez-moi vous expliquer avec un exemple.

public interface Attendance {
   boolean present() default DefaultAttendance.present;
}

public interface Timeline {
   boolean present() default DefaultTimeline.present;
}

public class TimeTravelingStudent implements Attendance, Timeline {

}

// which code gets called?
new TimeTravelingStudent().present();

Cela a-t-il déjà été défini dans le cadre du JDK 8?

J'ai trouvé les dieux de Java qui parlent de quelque chose de similaire ici http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html , mais sa partie de la liste de diffusion privée et je ne peux pas leur demander directement.

Pour plus de détails sur l’utilisation des valeurs par défaut dans JDK 8 et sur l’extension de l’interface Collection au support de lambdas: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662. pdf

76
Pyrolistical

La session vidéo à regarder est ici http://medianetwork.Oracle.com/video/player/1113272518001 C'est le concepteur qui parle de la fonctionnalité appelée Extensions virtuelles. Il explique également que cela ne rompt pas avec la compatibilité ascendante.

9
Peter Lawrey

La réponse à l'opération de duplication est:

Pour résoudre le problème d'héritage multiple, une classe implémentant deux interfaces fournissant une implémentation par défaut pour le même nom de méthode et la même signature doit fournir une implémentation de la méthode. [Article complet]

Ma réponse à votre question est la suivante: oui, il s'agit d'une forme d'héritage multiple, car vous pouvez hériter d'un comportement de parents différents. Ce qui manque, c'est d'hériter des états, i. e., attributs.

63
H-Man2

Je sais que c'est un ancien post, mais comme je travaille avec ce genre de choses ...

Vous aurez une erreur du compilateur, vous disant que:

 La classe TimeTravelingStudent hérite des valeurs par défaut non liées pour present () des types Attendance et Timeline référence à present est ambiguë, méthode present () dans la timeline et méthode present () dans la correspondance d’assistance.

8
Enkk

En bref: c'est une erreur de compilation, il faut écraser manuellement la méthode dans l'implémentation.


But de la méthode par défaut

L'objectif principal d'introduire la méthode par défaut dans Java 8 est de rendre l'interface extensible, sans casser les implémentations existantes (il y a tellement de bibliothèques Java tierces).

Et multiple inheritance comme en C++ est en fait destiné à être évité, ce n'est certainement pas le but de la méthode par défaut en Java.


Comment remplacer

2 options:

  • Remplacez la méthode, avec sa propre logique.
  • Remplacez la méthode, appelez une des méthodes de l'interface via super, format: <interface_name>.super.<method_name>();

Conseils:

  • méthode à partir de l'interface est public, alors n'oubliez pas d'ajouter le mot clé public lors de son remplacement.
4
Eric Wang

Ma réponse à votre question est la suivante: oui, il s'agit d'une forme d'héritage multiple, car vous pouvez hériter d'un comportement de parents différents. Ce qui manque, c'est d'hériter des états, i. e., attributs.

Oui, mais vous pouvez ajouter à votre interface des getters et des setters que les classes d'implémentation doivent ensuite implémenter. Néanmoins, les classes d'implémentation n'héritent pas d'attributs. Donc, AFAICS, cela ressemble plus à une solution de style trait que de solution de style à héritage multiple. 

4
OlliP

Il y a deux scénarios:

1) Tout d'abord, cela a été mentionné, où il n'y a aucune interface plus spécifique

public interface A {
   default void doStuff(){ /* implementation */ }
}

public interface B {
   default void doStuff() { /* implementation */ } 
}

public class C implements A, B {
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
  void doStuff(){
      B.super.doStuff();
  }
}

2) Deuxièmement, quand IS une interface plus spécifique:

   public interface A {
       default void doStuff() { /* implementation */ } 
    }

    public interface B extends A {
       default void doStuff() { /* implementation */ } 
    }

    public class C implements A, B {
    // will use method from B, as it is "closer" to C
    }
3
Andrejs

Si quelqu'un cherche toujours une réponse, si une classe implémente deux interfaces avec la même méthode par défaut, elle doit résoudre le problème de la désambiguïté en fournissant sa propre implémentation. Regardez this tutorial pour plus de détails sur le fonctionnement de l'héritage dans les méthodes par défaut.

2
mithil-studytrails