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 :

Sous-typer une valeur de retour de méthode générique


Sujet :

Langage Java

  1. #1
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut Sous-typer une valeur de retour de méthode générique
    Bonjour,

    Dans cet example
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	interface underType {
    		static interface A<B> {}
    		Object f();
    		A<?> g();
    		<N extends A<?>> N h();
    		static interface Child extends underType {
    			@Override String f();
    			@Override A<String> g();
    			@Override <N extends A<String>> N h();
                            // //@Override <N extends A<? extends String>> N h();
    		}
    	}
    Je n'arrive pas à surcharger h() dans Child ("The method h() of type underType.Child must override or implement a supertype method"), alors que <N extends A<String>> et <N extends A<? extends String>> sont des sous-types de <N extends A<?>>.
    Savez vous comment faire?

    Merci d'avance

  2. #2
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Salut,


    Citation Envoyé par shaiHulud
    <N extends A<String>> et <N extends A<? extends String>> sont des sous-types de <N extends A<?>>
    Je vois ce que tu veux faire, même si le polymorphisme permet d'avoir un type de retour covariant (ps: depuis Java 5), cela ne fonctionne qu'avec les classes simples, pas les génériques Java. Pour tester, sans aller jusqu'au wildcard, remplace le contenu du générique parent par N extends Object et celle du child par N extends String, String hérite d'Object et pourtant le compilateur t'empêche de compiler car ce dernier génère la même signature pour les deux méthodes mais l'un ne redéfinit pas l'autre selon lui. Tu es dans un cas de limitation du type erasure.

    J'avais écrit un article sur la limitations des génériques en Java, si ça t'intéresse...


    A+
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  3. #3
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut
    C'est bien ce que je craignais.
    Merci bcp Gugelhupf !

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Une telle chose est impossible certes.

    Mais pour information ça n'a rien à voir avec le type erasure, puisque après type erase toutes les méthodes h() renvoient simplement A, donc ont toutes la même signature.

    C'est avant le type erasure qu'elles n'ont pas la même signature.

    Quand une méthode est générique, c'est-à-dire qu'elle a une déclaration de types paramétrés, alors toute méthode qui cherche à la redéfinir doit proposer la même déclaration de types paramétrés, sans aucune différence, un point c'est tout. Une variation et les signatures deviennent incompatibles.

    Dans l'exemple proposé ici on ne comprend pas pourquoi, ça a l'air d'une limitation abusive et sans intérêt, puisque le type paramétré, N, est le type de retour des méthodes et donc une redéfinition de méthode devrait pouvoir donner comme type de retour un sous-type du type proposé avant redéfinition.

    C'est ce qu'on peut se dire face à cet exemple, nous pauvres humains, mais c'est parce qu'on oublie un peu vite qu'un type paramétré de méthode qui ne sert que comme type de retour, ça n'a aucune utilité. L'outil est là pour faire du type safe, et à la place on fait quelque chose qui est clairement le contraire du type safe.

    Dans le monde réel N devrait apparaître ailleurs, comme par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <N extends A<?>> N h(N param);
    Et là d'un seul coup c'est pas la même, si on s'amuse à remplacer <N extends A<?>> par quoi que ce soit d'autre ce n'est évidemment pas acceptable dans une redéfinition.

    Et le compilateur, lui, c'est tout ce qui l'intéresse : modifier les paramètres génériques, ce n'est pas acceptable pour une redéfinition. Le fait que cela aurait pu marcher dans la mesure où il se trouve par hasard que les paramètres génériques ne sont utilisés que comme type de retour, ce n'est pas son problème. De toute façon c'est un abus de syntaxe au départ.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut
    Merci beaucoup pour les détails thelvin, c'est très clair.

    Peux-tu détailler un peu ta remarque stp ?
    un type paramétré de méthode qui ne sert que comme type de retour, ça n'a aucune utilité

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Pas vraiment parce qu'en fait, il y a un intérêt. Mais, ce n'est pas celui qui était prévu par le mécanisme des génériques.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    interface DonneurDObjet {
      <T> T donneUnObjet();
    }
    Ça s'utilisera un peu comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DonneurDObjet donneur = recupererUnDonneur();
     
    // ...
     
    LocalDate date = donneur.donneUnObjet();
    Et à aucun moment le système ne sait que l'objet à donner est de type LocalDate. On compte juste sur le fait que l'appel à recupererUnDonneur() va nous filer un donneur qui donne des LocalDate, parce que le programmeur s'est arrangé pour que ce soit ça qu'on obtienne.

    Si on n'utilisait pas les paramètres, on aurait ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    interface DonneurDObjet {
      Object donneUnObjet();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DonneurDObjet donneur = recupererUnDonneur();
     
    // ...
     
    LocalDate date = (LocalDate) donneur.donneUnObjet();
    Un simple cast qui s'assure que l'objet donné est bien du type voulu.
    Et c'est exactement ce que fait le code générique. Un simple cast qu'on a pas besoin de taper.

    C'est à ça que sert le code : économiser de taper un cast qui sera fait automatiquement. Puisque de toute façon le cast est inévitable pour assurer le typage.

    Ce n'est pas grand-chose, et ce n'est pas là que réside l'intérêt des génériques. Le système n'est donc pas fait pour s'adapter à ça.

    Et en plus ça a un prix : il devient possible d'écrire quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <T> void ajouterDansListe(List<T> liste) {
      T nouveau = donneur.donneUnObjet();
      liste.add(nouveau);
    }
    Et là c'est le drame : pas de cast pour s'assurer que l'objet donné est bien du même type que la List. Nous avons perdu la sûreté du type. Tout ça parce que nous avons utilisé un type paramétré de méthode uniquement comme valeur de retour de cette méthode.

    Tout cela était une mauvaise idée, même si elle a l'air pratique de temps en temps.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Je pense que ton exemple (sans wildcard) aurait pu fonctionner en C#, voici un test (lien) que j'ai effectué :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    using System;
     
    public class Test
    {
    	public static void Main()
    	{
    		// your code goes here
    	}
     
    	interface Parent {}
     
    	interface Child : Parent {}
     
    	interface A 
    	{
    		T h<T>() where T : Parent;
    	}
     
    	interface B : A 
    	{
    		T h<T>() where T : Child; // Voir ICI
    	}
    }
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  8. #8
    Membre éprouvé
    Inscrit en
    Août 2010
    Messages
    1 124
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 1 124
    Points : 1 277
    Points
    1 277
    Par défaut
    Merci beaucoup à tous les 2 pour les précisions !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. ecrire à partir d'une macro sous excel une valeur dans une base sql server
    Par Guena5635 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 17/04/2008, 08h53
  2. [Console] Récupérer une valeur de retour
    Par lapanne dans le forum C#
    Réponses: 1
    Dernier message: 13/04/2007, 12h25
  3. [AJAX] Récupération d'une valeur en retour d'un php
    Par lodan dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 08/02/2007, 21h18
  4. Sous-état : une valeur par page de l'état
    Par Aitone dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 17/01/2007, 18h19
  5. Recuperer une valeur de retour?
    Par nic413 dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 06/06/2006, 11h07

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