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 :

Exercice sur les génériques pour développeur confirmé


Sujet :

Langage Java

  1. #1
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut Exercice sur les génériques pour développeur confirmé
    Bonjour,

    Je bute sur un exercice du livre Thinking in Java (jusqu'à présent je les enchainais tous ).
    J'ai pas envie de payer 20$ pour le corrigé de tous les exercices qui sont à télécharger sur le site du livre (surtout qu'ils sont pas disponibles pour la dernière édition), donc si quelqu'un a la solution, je suis preneur.
    Voici donc l'énoncé (libre de droit) :

    Create a generic class Generic1<T> with a single method that takes an argument of type T. Create a second generic class Generic2<T> with a single method that returns an argument of type T. Write a generic method with a contravariant argument of the first generic class that calls its method. Write a second generic method with a covariant argument of the second generic class that calls its method. Test using the typeinfo.pets library.

    La libraire typeinfo.pets contient une hiérarchie de classes avec Pet comme super classe et des classes enfants comme Cat, Dog, etc.

    Alors les pros ?

  2. #2
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    775
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 775
    Par défaut
    Bonjour,

    Elle est où la question ?

  3. #3
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Je cherche la solution à l'exercice. Je n'ai pas vraiment de question précise dessus car je ne suis pas sur d'avoir bien compris l'énoncé. Toute piste est la bienvenue.

  4. #4
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    775
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 775
    Par défaut
    Bon juste une piste alors, comme ça a vue de nez comme ça parle de contravariant et de covariant, c'est certainement pour te faire utiliser des wildcards avec les mots clés extends et super.
    Comme ça tu passes d'un type à l'autre.

    Bon courage, mais bon les exercices des bouquins c'est un peu bof, en pratique il vaut mieux simplifier que de s'amuser a ce genre de manip.

  5. #5
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Je suis bien d'accord qu'en pratique il faut simplifier.
    Voilà ce que j'avais commencé à écrire :
    Code : 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
    24
    25
    class Generic1<T> {
     
      public void meth(T t) { }
     
    }
     
    class Generic2<T> {
     
      public T meth(T t) {
        return t;
      }
     
      public void meth1(Generic1<? super Pet> u) {
        u.meth(new Cat());
      }
     
      public void meth2(Generic2<? extends Pet> v) {
        // Je vois pas comment appeler v.meth() ici ..
      }
     
    }
     
    class Pet { }
     
    class Cat extends Pet { }

  6. #6
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,


    La méthode de la seconde classe se contente de retourner un élément de type T sans paramètre, donc il suffit de faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Generic2<T> {
     
      public T meth() {
        return t;
      }
     
      public void meth2(Generic2<? extends Pet> v) {
        Pet pet = v.meth();
      }
     
    }


    Mais bon perso je ne trouve pas cela très clair présenté comme cela.

    En général je préfère utiliser les collections pour parler de cela...



    a++

  7. #7
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Generic2<T> {
     
      public T meth() {
        return t;
      }
     
      public void meth2(Generic2<? extends Pet> v) {
        Pet pet = v.meth();
      }
     
    }
    Comment instancier un objet t du type générique T dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public T meth() {
        return t;
      }
    ?

  8. #8
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Tesing Voir le message
    Comment instancier un objet t du type générique T dans :
    Tu ne peux pas (mais je ne pense pas que l'intérêt de la question soit là).

    Disons que ta classe Generic2 pourrait être défini comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Generic2<T> {
    	private final T t;
     
    	public Generic2(T t) {
    		this.t = t;
    	}
     
    	public T meth() {
    		return t;
    	}  
    }






    Mais comme je l'ai dit je préfère utilise les collections pour décrire l'utilisation de la contravariance/covariance. Si j'ai le temps j'essayerais de faire un topo rapide là dessus...


    a++

  9. #9
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Ok, merci pour ta réponse.
    Effectivement, je suis un peu déçu du chapitre sur les génériques de ce bouquin. Pour autant, les autres sont très complets.

  10. #10
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 586
    Par défaut
    Citation Envoyé par Tesing Voir le message
    Write a generic method with a contravariant argument of the first generic class that calls its method. Write a second generic method with a covariant argument of the second generic class that calls its method. Test using the typeinfo.pets library.
    Vu que ce sont les méthodes, qui doivent être génériques, j'ai l'impression que ce serait plutôt ça :

    Code : 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
    public class TestGeneric1And2 {
     
      public static <T> void testGen1(Generic1<? super T> gen1, T t) {
        System.out.println("Called testGen1");
        gen1.method(t);
      }
     
      public static <T> T testGen2(Generic2<? extends T> gen2) {
        System.out.println("Called testGen2");
        return gen2.method();
      }
     
      public static void main(String[] args) {
        Generic1<Pet> gen1 = new Generic1<Pet>();
        testGen1(gen1, new Dog());
     
        Generic2<Cat> gen2 = new Generic2<Cat>(new Cat());
        Pet pet = gen2.method();
        pet.doSomething();
      }
     
    }
    Ce qui se voit mieux avec les collections :

    Code : 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
    24
    25
    26
    27
    public static <T> void insertInMiddle(List<? super T> list, T item) {
      list.add(list.size()/2, item);
    }
     
    public static <T> T getMiddleElement(List<? extends T> list) {
      return list.get(list.size()/2);
    }
     
    public static void main(String[] args) {
      List<Pet> pets = new ArrayList<Pet>();
      pets.add(new Dog());
      pets.add(new Cat());
      pets.add(new Rat());
     
      System.out.println(pets);
      insertInMiddle(pets, new Bird());
      System.out.println(pets);
     
      List<Dog> dogs = new ArrayList<Dog>();
      dogs.add(new Dog());
      dogs.add(new Dog());
      dogs.add(new Dog());
     
      System.out.println(dogs);
      Pet pet = getMiddleElement(dogs);
      System.out.println(pet);
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  11. #11
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Ok, merci, effectivement, ça me paraît juste.

  12. #12
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Mais comme je l'ai dit je préfère utilise les collections pour décrire l'utilisation de la contravariance/covariance. Si j'ai le temps j'essayerais de faire un topo rapide là dessus...
    Je m'y met... Attention ca risque d'être assez long...




    On reprendra donc la classe Pet avec ses sous-classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Pet {
    	public String getName();
    }
     
    class Cat extends Pet {}
    class Dog extends Pet {}

    Notre application va manipuler les listes d'animaux, et donc on va avoir besoin de quelques utilitaires.
    • La première consistera simplement à afficher le nom de chaque animal.
    • La seconde permettra d'ajouter un chien dans une liste.



    A première vue, on pourrait se contenter de ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public static void print(List<Pet> list) {
    	for (Pet pet : list) {
    		System.out.println( pet.getName() );
    	}
    }
     
    public static void addDog(List<Pet> list, Dog aDog) {
    	list.add( aDog );
    }




    Maintenant, dans notre application on est amené à utiliser plusieurs types de listes.
    Il n'y a aucun soucis avec les List<Pet>, mais il est impossible d'utiliser une List<Dog> avec nos méthodes, car les types ne sont pas compatible !!!

    En effet ce n'est pas la même chose. Une List<Dog> ne peut contenir que des Dog (ou type enfants), alors qu'une List<Pet> peut contenir aussi des Cat, Pet ou tout autre classe fille de Pet...

    Du coup le compilateur interdit toute tentative de conversion de ce style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    List<Dog> dogs = ...
    List<Pet> pets = (List<Pet>) dogs; // ERREUR DE COMPILATION
     
    pets.add( new Cat() ); // ????
    Sinon on pourrait se retrouver dans des cas incohérent, par exemple où on ajouterais un Cat dans une liste de Dog...


    Mais du coup le code est moins générique, dans le sens où il faudrait faire une méthode print() pour chaque type de liste...

    La covariance/contravariance vient pallier à cela, en diminuant un peu le typeage.







    La covariance permet de définir partiellement le type. Ainsi List<? extends Pet> représente toutes les listes paramétrées avec la classe Pet ou un type enfant, et est donc compatible avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<Dog> dogs = ...
    List<? extends Pet> pets = dogs; // OK
    Par contre, comme on ne connait pas le type précis du paramétrage Generics T, on ne peut pas utiliser les méthodes qui utilisent ce paramétrage en paramètre (comme add(T) par exemple). En effet puisqu'on ne connait pas le type précis à utiliser, on ne peut pas appeler la méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    List<? extends Pet> pets = ...
     
    pets.add( new Dog() ); // ERREUR DE COMPILATION
    Dans ce cas précis, rien ne permet d'afficher que la liste peut accepter des Dog (ce pourrait tout à fait être une List<Cat> après tout).


    Par contre, il n'y a aucun problème à utiliser les méthodes qui retourne ce type paramétré T. En effet, bien que l'on ne connaisse pas le type précis, on sait qu'il s'agit au moins d'un Pet. Qu'on ait affaire à une List<Pet>, List<Cat>, List<Dog> ou de toute autre List<classe-fille-de-Pet>, on sait que ce sera forcément un Pet.

    Du coup notre méthode print() pourra être changer comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    public static void print(List<? extends Pet> list) {
    	for (Pet pet : list) { // utilise iterator() qui retourne Iterator<T>
    		System.out.println( pet.getName() );
    	}
    }
    Désormais notre méthode est utilisable avec des List<Pet>, List<Cat>, List<Dog>... simplement en changeant sa signature.







    La contravariance, c'est exactement l'inverse.
    Ainsi List<? super Dog> correspond à une liste paramétré avec Dog ou un type parent (donc Pet ou Object dans ce cas précis).
    Du coup on peut très bien utiliser les méthodes qui utilisent le type paramétré en paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    List<? super Dog> dogs = ...
     
    dogs.add( new Dog() ); // OK
    En effet, on est sûr que le paramétrage correspond à un type parent, donc on peut très bien lui passer une valeur correcte.

    Du coup, notre method addDog() pourrait s'écrire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static void addDog(List<? super Dog> list, Dog aDog) {
    	list.add( aDog );
    }
    Désormais notre méthode est utilisable avec des List<Dog>, List<Pet> ou List<Object>... bref toutes les listes pouvant contenir un Dog !


    Comme la covariance, la contravariance nous limite sur certaine méthode. Ainsi comme on ne connait pas le type précis, on ne peut pas utiliser les méthodes retournant un objet paramétré avec T, puisqu'on ignore son type.
    Enfin plus précisément dans ce cas là on peut appeler la méthode, mais sa valeur de retour ne sera pas typé du tout :
    [code]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    List<? extends Dog> dogs = ...
     
    dogs.add( new Dog() ); // OK
    Object o = dogs.get(0); // OK, mais pas typé




    Bref : les Generics imposent un typeage stricte, que les notions de covariance/contravariance permettent d'atténuer (avec quelques limitations).



    a++

  13. #13
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    impeccable, c'est très clair

  14. #14
    Expert confirmé
    Avatar de le y@m's
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2005
    Messages
    2 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Février 2005
    Messages : 2 636
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    ...
    Super post, ça mériterait bien un billet ou un mini article .

    Par contre je pense que tu as pas fait une erreur de frappe/copier/coller dans la partie contravariance où dans le code il y a extends et pas super.
    Citation Envoyé par adiGuba Voir le message
    La contravariance, c'est exactement l'inverse.
    Ainsi List<? super Dog> correspond à une liste paramétré avec Dog ou un type parent (donc Pet ou Object dans ce cas précis).
    Du coup on peut très bien utiliser les méthodes qui utilisent le type paramétré en paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    List<? extends Dog> dogs = ...
    
    dogs.add( new Dog() ); // OK
    En effet, on est sûr que le paramétrage correspond à un type parent, donc on peut très bien lui passer une valeur correcte.

    Du coup, notre method addDog() pourrait s'écrire comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static void addDog(List<? extends Dog> list, Dog aDog) {
    	list.add( aDog );
    }
    Désormais notre méthode est utilisable avec des List<Dog>, List<Pet> ou List<Object>... bref toutes les listes pouvant contenir un Dog !
    Je ne répondrai à aucune question technique par MP.

    Pensez aux Tutoriels et aux FAQs avant de poster ;) (pour le java il y a aussi JavaSearch), n'oubliez pas non plus la fonction Rechercher.
    Enfin, quand une solution a été trouvée à votre problème
    pensez au tag :resolu:

    Cours Dvp : http://ydisanto.developpez.com
    Blog : http://yann-disanto.blogspot.com/
    Page perso : http://yann-disanto.fr

  15. #15
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par le y@m's Voir le message
    Super post, ça mériterait bien un billet ou un mini article .
    J'essayerais de faire un truc plus concret un jour... mais je suis sur un autre article en ce moment

    Citation Envoyé par le y@m's Voir le message
    Par contre je pense que tu as pas fait une erreur de frappe/copier/coller dans la partie contravariance où dans le code il y a extends et pas super.
    Oui bien vu !
    Je corrige cela vite fait


    a++

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    190
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 190
    Par défaut
    La conclusion de l'article est-elle que le code suivant fonctionne?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    List<Dog> dogs = ...
    addPet(dogs, new Dog());
    printPet(dogs);
     
    List<Cat> cats = ...
    addPet(cats, new Cat());
    printPet(cats);

  17. #17
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Pour le print() oui... mais pas pour le add() puisque les types sont incompatibles :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static void addDog(List<? super Dog> list, Dog aDog) {
    		list.add( aDog );
    	}

    Mais il est vrai qu'on pourrait vouloir aller plus loin sur cet exemple, même si on sort un peu de la covariance/contravariance...

    La différence c'est qu'ici on a un paramètre en plus, dont le type doit correspond au type max du paramètrage.
    Tel quel il faudrait dupliquer les méthodes, afin de garder cette correspondance entre le paramétrage de la list et le paramètre qu'on va lui ajouter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	public static void addPet(List<? super Pet> list, Pet aPet) {
    		list.add( aPet );
    	}
    	public static void addCat(List<? super Cat> list, Cat aCat) {
    		list.add( aCat );
    	}
    	public static void addDog(List<? super Dog> list, Dog aDog) {
    		list.add( aDog );
    	}

    Pour cela, il faut paramétré la méthode avec les Generics (indépendamment de la classe dans laquellle elle se trouve).
    Cela se fait assez simplement en précédant le type de retour par un paramétrage Generics :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static <P> void addPet(List<? super Pet> list, Pet aPet) {
    		list.add( aPet );
    	}
    Pour l'instant ce paramétrage est complètement inutile puisqu'on ne l'utilise pas.
    Mais il va nous permettre de lier le type paramétré de la List au type du second paramètre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    	public static <P> void addPet(List<? super P> list, P aPet) {
    		list.add( aPet );
    	}
    Et notre méthode peut être utilisé avec n'importe quelle combinaison, à condition que cela soit cohérent bien sûr :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	List<Pet> pets = ...
    	addPet(pets, new Pet()); // OK
    	addPet(pets, new Dog()); // OK
    	addPet(pets, new Cat()); // OK
     
    	List<Cat> cats =  ...
    	addPet(cats, new Pet()); // ERREUR
    	addPet(cats, new Dog()); // ERREUR
    	addPet(cats, new Cat()); // OK
     
    	List<Dog> dogs = ...
    	addPet(dogs, new Pet()); // ERREUR
    	addPet(dogs, new Dog()); // OK
    	addPet(dogs, new Cat()); // ERREUR

    Seul bemol : à l'intérieur de notre methode, le paramètre 'aPet' est vue comme un Object.
    On fait la méthode est tellement générique qu'on pourrait l'utiliser pour ajouter n'importe quoi dans n'importe quelle liste :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	List<Date> dates = ...
    	addPet(dates, new Date());
    Selon les cas ce comportement peut être souhaitable, mais pas forcément.
    Par exemple si on veut utiliser des méthodes de "Pet".

    Dans ce cas là il faut modifier le type de "P" via un wildcard. Par exemple pour que ce soit obligatoirement un Pet (ou fils) il suffit d'utilier <P extends Pet> à la place de <P> :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	public static <P extends Pet> void addPet(List<? super P> list, P aPet) {
    		// aPet est de type Pet, donc on peut utiliser ses méthodes :
    		System.out.println(" adding " + aPet.getName() );
    		list.add( aPet );
    	}
    Désormais, notre méthode est limité au cas d'utilisation où le type P correspond à un Pet (ou classes fils)



    Attention : cela ressemble à la variance/covariance mais ce n'est pas tout à fait la même chose.
    Par exemple on ne peut pas utiliser <P super Pet> dans le paramétrage d'une classe/méthode, car cela n'a pas de sens...


    Reste le problème du nommage du type Generics "P"... Par convention on doit utiliser une lettre en majuscule, mais ce n'est pas super lisible lorsqu'on en manipule beaucoup



    a++

  18. #18
    Membre expérimenté
    Avatar de Tesing
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Par défaut
    Je suis partant pour synthétiser les réponses et écrire un article didactique sur le sujet.

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

Discussions similaires

  1. aide pour exercice sur Les boucles
    Par hotdogFRANCE dans le forum C#
    Réponses: 3
    Dernier message: 13/03/2009, 09h43
  2. aide pour un exercice sur les tableaux
    Par mimiif dans le forum Caml
    Réponses: 9
    Dernier message: 30/05/2008, 16h49
  3. aide pour exercice sur les structures
    Par demetria dans le forum C
    Réponses: 10
    Dernier message: 25/09/2007, 23h11
  4. Besoin d'aide pour un exercice sur les registres
    Par zakuza dans le forum Assembleur
    Réponses: 5
    Dernier message: 14/04/2006, 15h23
  5. Réponses: 4
    Dernier message: 28/07/2005, 17h22

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