IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

Default methods et interface en SE 8


Sujet :

Langage Java

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 48
    Points
    48
    Par défaut Default methods et interface en SE 8
    Bonjour,

    Dans la version 8 de Java, on autorise l'implémentation de code dans les interfaces.
    D'un point de vue conceptuel, c'est a mon avis un retour en arrière dangereux dont je ne vois pas les bénéfices.
    A l'origine l'interface est la pour interdire l'héritage multiple et ces problèmes. Certes si 2 interfaces proposent le même code en Java 8 on peut stipuler directement <Interface>.super.<méthode> mais c'est au développeur d’être vigilant (et de faire le boulot de vérification.)
    L'utilisation de classes abstraites permet déjà de factoriser du code. Quant aux problématiques d'extension ou d'abstraction d'interface l'utilisation des patterns Adapter, Façade, Composite et Bridge apporte déjà des réponses.
    Et quid des compatibilités entre ancienne interface et nouvelle...
    Bref, j'aimerais bien connaitre un cas qui justifie cette évolution ou entendre vos argumentations en faveur de ce nouveau type d'interface.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Cas le plus basique et déjà répété mille fois sur le forum

    on ajoute la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Stream<T> stream()
    à l'api java.util.Collection<T>.

    A partir de là deux alternatives:
    on fournis un mécanisme par défaut et tout à coup toutes les apis étendant Collection sont compatibles avec les Stream.
    On ne fourni pas de mécanisme par défaut et on se retrouve avec sur les bras un parc de 99% des programmes écris en java qui ne tournent plus sur java 8 car il leur manquent des méthodes...

    Donc le but principal, c'est de rendre les interfaces évolutives dans le temps.

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Par ailleurs, j'ai toujours trouvé que les "classes utilitaires," rapides à naître quand on définit des interfaces, exemples : Collections, Comparators ; eh bien ces classes utilitaires j'ai toujours trouvé qu'elles n'étaient pas très satisfaisantes.

    D'une part la place de ces méthodes est avec ce qui justifie leur existence et qui sait pourquoi elles sont là : l'interface.
    D'autre part lorsque ces méthodes agissent sur au moins une instance de l'interface, elles devraient être des méthodes d'instance, pas des méthodes static. C'est ridicule de créer une classe abstraite artificielle dont il faudra toujours hériter pour couvrir ce besoin : par définition l'idée d'une interface est d'être libre d'hériter d'une classe ou non.

    Les méthodes static dans les interfaces, et les default methods, permettent ceci, ce qui est plus satisfaisant à mon goût.
    Je ne vois pas, par ailleurs, où il y a régression et en quoi le programmeur devrait être plus attentif. Le compilateur continue d'assurer ce que doit.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  4. #4
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    @Tchize :
    Pas vraiment convaincu...
    Tout d'abord sur la forme : il faut utiliser les "default méthods" pour des questions d'évolution et de compatibilité ...? On n’utilise pas une technique nouvelle pour de la rétrocompatibilité. Hors sujet.
    Ensuite sur le fond, on peut toujours réaliser une conversion d'une interface en une autre (voir le pattern Adapter par exemple)

    Pour reformuler ma question : En dehors du fait de rapprocher Java de Scala, pourquoi avoir ouvert une implémentation dans les interfaces, et perdre pour le coup l'universalité des interfaces (dans le sens couplage faible interface-classe) ?

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par aspire Voir le message
    Pas vraiment convaincu...
    Tout d'abord sur la forme : il faut utiliser les "default méthods" pour des questions d'évolution et de compatibilité ...? On n’utilise pas une technique nouvelle pour de la rétrocompatibilité. Hors sujet.
    Ensuite sur le fond, on peut toujours réaliser une conversion d'une interface en une autre (voir le pattern Adapter par exemple)
    Et pourtant les méthodes par défaut permet de faire évoluer les APIs tout en conservant la rétrocompatibilité.

    Avant Java 8 les interfaces devaient être immuable.
    C'est à dire qu'une fois qu'elles sont intégré dans une API, on ne peut plus les modifier sans casser potentiellement toutes les codes utilisant la-dites interfaces.
    Les méthodes par défaut permettent de faire évoluer les interfaces sans tout casser (même s'il peut rester des cas d'incompatibilités des "sources").


    Le pattern Adapter c'est bien beau, mais cela ne s'adapte pas à tout les cas.
    Prenons un exemple simple : l'ajout de la méthode sort(Comparator) dans List.
    Comment ferais-tu pour ajouter cette méthode dans l'interface List sans tout casser ?


    Citation Envoyé par aspire Voir le message
    Pour reformuler ma question : En dehors du fait de rapprocher Java de Scala, pourquoi avoir ouvert une implémentation dans les interfaces, et perdre pour le coup l'universalité des interfaces (dans le sens couplage faible interface-classe) ?
    On ne perd rien du tout. Les interfaces restent bien distinctes des classes du fait de leur absence d'état.

    Quand au problème de l'héritage multiple... il n'existe pas vraiment du fait de l'absence d'état.

    Pour que cela pose un problème il faut implémenter deux interfaces différentes spécifiant la même méthode sans jamais l'implémenter.
    Et dans ce cas là on te demande d'implémenter une méthode de l'interface : quoi de plus normal lorsque tu implémentes une interface !



    Bref : les méthodes par défaut permettent de faire évoluer les APIs existantes, sans casser la rétro.

    a++

  6. #6
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Je ne remets pas en cause le fait qu'il est certes plus simple de pouvoir modifier directement une interface.
    Mais c’était justement le caractère immuable et peu couplé qui était intéressant et sans ambiguïté aucune. Je trouve que l'on revient sur la séparation de base entre interface et classe via une "sorte" d'héritage multiple qui ne dit pas son nom.
    D'ailleurs aujourd'hui la différence entre classe abstraite et interface se réduit de beaucoup (même si oui il y a absence d’état ou d'attribut, on ne peut pas instancier et les accesseurs restent différents...).
    En ce qui concerne les problèmes d’héritage multiple je ne suis pas d'accord avec ton argument "en absence d’état". Prenons le cas de 2 méthodes différentes (avec du code par défaut) de même signature dans 2 interfaces différentes; la classe implémentant les 2 interfaces, il faudra bien spécifier laquelle utiliser. Je crois que Scala utilise un arbre de d'héritage. Certes, c'est un cas particulier peu fréquent mais il existe.
    Quant a utiliser des interfaces avec des méthodes d'extension ou des classes abstraites je verrai à l'usage.

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par aspire Voir le message
    Prenons le cas de 2 méthodes différentes (avec du code par défaut) de même signature dans 2 interfaces différentes; la classe implémentant les 2 interfaces, il faudra bien spécifier laquelle utiliser.
    En l'absence de default, il le fallait aussi, donc je ne vois pas où est le soucis . On n'a rien retiré au programmeur.

  8. #8
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par aspire Voir le message
    Mais c’était justement le caractère immuable et peu couplé qui était intéressant et sans ambiguïté aucune. Je trouve que l'on revient sur la séparation de base entre interface et classe via une "sorte" d'héritage multiple qui ne dit pas son nom.
    En quoi est-ce bien d'avoir des API qui ne peuvent pas évoluer ?
    Car dans ce cas les évolutions du langage sont inutile, ou impliqueraient de dupliquer des API entières afin de les utiliser... ce qui les rendraient moins utilisable.


    Citation Envoyé par aspire Voir le message
    D'ailleurs aujourd'hui la différence entre classe abstraite et interface se réduit de beaucoup (même si oui il y a absence d’état ou d'attribut, on ne peut pas instancier et les accesseurs restent différents...).
    Oui on peut dire qu'il y a 4 niveaux :
    • Les interfaces pures qui ne font que décrire un contrat.
    • Les interfaces avec méthodes par défaut qui rajoutent des comportements basés sur le contrat.
    • Les classes abstraites qui proposent une implémentation partielle.
    • Les classes concrètes qui proposent une implémentation complète.


    Et dans plusieurs cas les interfaces avec méthodes par défaut pourraient remplacer certaines classes abstraites sans état.


    Citation Envoyé par aspire Voir le message
    En ce qui concerne les problèmes d’héritage multiple je ne suis pas d'accord avec ton argument "en absence d’état". Prenons le cas de 2 méthodes différentes (avec du code par défaut) de même signature dans 2 interfaces différentes; la classe implémentant les 2 interfaces, il faudra bien spécifier laquelle utiliser.
    Et donc en implémentant une interface on t'impose d'implémenter ses méthodes... Il n'y a rien d'illogique à cela et c'en est presque normale.



    Quand je dis que c'est moins courant, c'est surtout qu'une grande partie des problèmes d'héritages proviennent des états des objets.
    Il y a plusieurs niveaux d'héritages multiples :
    • L'héritage multiple des types (ce que Java possède depuis toujours : un même objet peut avoir plusieurs types).
    • L'héritage multiple des implémentations, introduit donc par les méthodes par défaut.
    • L'héritage multiple des états, toujours absent de Java.


    Or les principaux problèmes d'héritages multiples sont lié à l'utilisation conjointes de ces deux derniers points : l'héritage multiple des implémentations et des états, car il devient plus difficile de hiérarchiser les implémentations.

    Ce n'est pas le cas avec les méthodes par défaut :
    • Une méthode définie dans une classe (abstraite ou pas) sera toujours prioritaire sur l'implémentation par défaut.
      En fait dès que la méthode est définie dans une classe de la hierarchie il n'y a plus aucun problème quelque soit le nombre de méthode par défaut.
    • Une méthode par défaut peut redéfinir une méthode, et ainsi devenir l'implémentation la plus spécifique, ce qui permet d'éviter une grande partie des problèmes de l'héritage en triangle ou losange (avec un etat c'est différent car on ne peut pas parler d’implémentation plus spécifique).


    Les cas problématiques de l'héritage multiple s'en trouvent grandement réduit, et le principal cas est celui que tu présentes : une même méthode par défaut définie dans deux interfaces distinctes.




    Enfin ce n'est pas parce qu'il y a des cas qui provoque des ambiguités ou des erreurs de compilation que c'est forcément mauvais.
    Il était déjà possible d'écrire plusieurs codes tout autant problématique avant Java 8...


    a++

  9. #9
    Membre du Club
    Homme Profil pro
    Inscrit en
    Novembre 2011
    Messages
    79
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2011
    Messages : 79
    Points : 48
    Points
    48
    Par défaut
    Merci pour ces échanges qui m'ont permis d’approfondir certains aspects de Java 8 que je n'avais fait que parcourir rapidement.
    Parmi mes lectures :
    http://blog.joda.org/2014/06/java-8-iterable-woes.html

    J'ai trouvé cet article intéressant dans le sens ou l'auteur s'interroge sur l'impact des default methods, trouve certaine limite (que je ne juge pas) et donne un exemple sur le fait de ne pas ajouter certaines méthodes aux interfaces (ici des Streams). Quant à sa dernière question, seul l'avenir nous le dira...

  10. #10
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Ce point de vue là me semble plus discutable en effet.



    Le fait d'ajouter des méthodes par défaut dans une interface peut être considéré comme une "pollution" pour la classe qui l'implémente, en augmentant le nombre de méthode de la classe.
    Selon les cas cela peut s'avérer gênant en effet... mais on garde la possibilité de ne pas implémenter l'interface.


    Persos je dirais la même chose de la classe Object, qui nous impose 5 méthodes de synchronisation dont l'utilité est très limité dans la grande majorité des cas.



    a++

  11. #11
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Enfin en l'occurrence l'article ne dit rien d'autre que "quand je dis que mon objet est itérable, je veux pas dire que le langage peut proposer d'autres syntaxes pour l'itérer que celle que j'aime bien !"

    Euh.... Tous les commentaires de l'article, lui ont posé une question très simple : pourquoi ? Je vois pas bien en quoi ses réponses... Y répondent.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  12. #12
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    @thelvin : je peux comprendre cela : c'est juste une volonté de ne pas "polluer" l'API de la classe avec une multitude de méthode.
    C'est pas forcément souhaitable...




    Sinon juste pour revenir aux méthodes par défaut : leurs intérêts premier pour moi reste le fait de pouvoir faire évoluer des API existante basée sur une abstractions fortes (via des interfaces).
    Bien sûr on pouvait faire cela via des méthodes static, mais c'est à la fois moins pratique à l'usage, mais également moins performant car cela ne permet pas aux implémentations concrètes d'utiliser une implémentation qui leurs est propre.

    Et pour moi c'est là la grande force des méthodes par défaut !


    a++

  13. #13
    Expert éminent sénior Avatar de Uther
    Homme Profil pro
    Tourneur Fraiseur
    Inscrit en
    Avril 2002
    Messages
    4 552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Tourneur Fraiseur

    Informations forums :
    Inscription : Avril 2002
    Messages : 4 552
    Points : 15 463
    Points
    15 463
    Par défaut
    Je suis d'accord sur le fait que c'est une bonne chose de pouvoir faire évoluer les interfaces, mais je pense qu'il n'y avait pas besoin de transformer les interfaces en quasi en classes abstraites avec une syntaxe différente pour faire cela.

    Si le but était seulement de permettre l'extension des interfaces, il suffisait de pouvoir définir sur les interfaces des "méthodes d'extension" qui n'auraient pas obligatoirement eu à être implémentées (un appel a une méthode non implémentée aurait déclenché une exception). Certes il aurait fallu que les classes qui veulent utiliser les nouvelles méthode fassent elle même l’implémentation, mais je pense que ça aurait été bien plus cohérent au final.

  14. #14
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Je vois toujours pas le rapport avec les classes abstraites, personnellement.
    Une classe abstraite ça a jamais été autre chose qu'un début d'implémentation de classe avec état, c'est-à-dire exactement ce qu'une interface ne peut toujours pas être.

    Ce que les default methods font, c'est genre fusionner les interfaces avec les classes utilitaires qu'on crée pour elles. Et je vois très bien en quoi c'est exactement ce qu'on veut, mais je vois moins bien où sont les problèmes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Uther Voir le message
    Si le but était seulement de permettre l'extension des interfaces, il suffisait de pouvoir définir sur les interfaces des "méthodes d'extension" qui n'auraient pas obligatoirement eu à être implémentées (un appel a une méthode non implémentée aurait déclenché une exception). Certes il aurait fallu que les classes qui veulent utiliser les nouvelles méthode fassent elle même l’implémentation, mais je pense que ça aurait été bien plus cohérent au final.
    Sauf que cela aurait été complètement inutilisable dans la majorité des cas... à moins de connaitre précisément l'implémentation de toutes les classes que tu utilises.
    Ce qui est totalement impossible dans bien des cas !

    Du coup toutes ces nouvelles méthodes n'auraient pas pu être utilisées de manière sécurisé.


    Et justement le rôle des méthodes par défaut est de proposer une implémentation basique, basé uniquement sur le contrat de l'interface, afin de garantir que le code fonctionnera, même s'il ne sera pas forcément optimisé.


    a++

Discussions similaires

  1. [Java 8] default method: pas de final possible
    Par professeur shadoko dans le forum Langage
    Réponses: 19
    Dernier message: 09/09/2014, 11h26
  2. [Java 8+] A propos des 'default' methodes
    Par 0xNoob dans le forum Langage
    Réponses: 7
    Dernier message: 22/05/2014, 23h47
  3. methode d'interface inaccessible depuis classe metier!
    Par touftouf57 dans le forum Débuter avec Java
    Réponses: 14
    Dernier message: 14/04/2009, 12h06
  4. methode static interface
    Par samtheh dans le forum Langage
    Réponses: 3
    Dernier message: 15/10/2006, 20h25
  5. [Interfaces] Comment définir l'emplacement mémoire des methodes ?
    Par Clorish dans le forum API, COM et SDKs
    Réponses: 2
    Dernier message: 16/12/2005, 15h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo