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 :

Generics... moi pas comprendre qqch


Sujet :

Langage Java

  1. #1
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut Generics... moi pas comprendre qqch
    Sur cette page, dans "les méthodes génériques":
    http://lroux.developpez.com/article/...ge_5#Lgenerics

    Il y a quelque chose que je ne comprends pas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    static void addResidents(List<? extends Resident> newComers,
                             List<Resident> residents)
    {
      for(Resident n: newComers)
      {
        residents.add(n); // erreur de compilation
      }
    }
    Pourquoi il y a une erreur de compilation à la ligne indiquée?
    Pour chaque (? extends résident) de la liste newComers, donc qui est d'un type inconnu, mais dont on sait qu'il hérite de Resident, on veut l'ajouter dans la liste des résidents, paramétrée par le type Resident.
    Donc où est le problème... Il attend un Resident, on lui ajoute quelque chose qui étend résident...
    C'est comme si on paramétrait par un Object, et qu'on lui mettait une String...
    Ca ne devrait pas poser de problèmes...

    Pouvez-vous m'éclaircir ?

  2. #2
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    Salut,

    Il te renvoie quelle erreur ?

    mavina
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

  3. #3
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par mavina
    Salut,

    Il te renvoie quelle erreur ?

    mavina
    Arf, je ne sais pas, je n'ai pas testé...
    J'ai juste lu ça dans la FAQ...

  4. #4
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    ah pardon j'ai mal compris la question ^^
    (pas trop réveillé )

    Il est apparemment impossible de modifier une liste passée en paramètre, il faut en renvoyer une ...
    Cette construction a pourtant une limitation. Il est en effet impossible de modifier la liste dans le corps de la méthode, car nous ne connaissons pas le type effectif (si ce n’est que c’est un type inconnu dont le supertype est Resident). Toute tentative d’ajout d’élément nous confronterait à un problème de compatibilité de type entre le type effectif et le type de l’objet à ajouter.
    mavina
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

  5. #5
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    En fait je suis confronté à un problème que je n'arrive pas à résoudre (à part par un @SuppressWarnings)...

    J'ai une classe AbstractCell<T extends ObjetGeometrique>.
    avec une methode void set(T t);
    Ensuite, j'ai 2 classes telles que:
    class Cube extends AbstractCell<Cube>
    class Sphere extends AbstractCell<Sphere>

    qui redéfinissent donc la méthode void set(Cube c) et void set(Sphere s)...

    Jusque là tout va bien...

    J'ai un problème dans un cas particulier d'utilisation...
    Je voudrais que mon renderer puisse prendre comme paramètre Cube ou Sphere selon le cas...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object value = ...
    @SuppressWarnings("unchecked") AbstractCell renderer = new CubeCell();
    if(value instanceof Cube) {
         renderer = cubeRenderer;
         renderer.set((Cube) value);
    } else if(value instanceof Sphere) {
         renderer = sphereRenderer;
         renderer.set((Sphere) value);
    }
    renderer.setBackground(bg);
    (par exemple, pour ne pas faire .setBackground(bg) dans toutes les alternatives...)

  6. #6
    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,

    Je pense qu'il s'agit d'une coquille dans l'article, et qu'il voulait dire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    static void addResidents(List<? extends Resident> newComers,
                             List<? extends Resident> residents)
    En effet dans ce cas cela peut poser problème car le type réel des listes peut être imcompatible.

    Un exemple similaire avec la classe Number :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        public static void addNumbers(List<? extends Number> input,
                List<? extends Number> output){
     
            for(Number n: input) {
                output.add(n); // erreur de compilation
            }
        }
    L'erreur de compilation vient du fait que le type réel du Number de la liste en input peut être différent de celui de la seconde liste. En effet on peut très bien utiliser cette méthode de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            List<Double> list1 = new ArrayList<Double>();
            List<Integer> list2 = new ArrayList<Integer>();
            addNumbers(list1, list2);
    Du coup si le add() était accepté à la compilation, on ajouterai un Double dans un tableau de Integer...


    Et la solution proposé est d'utiliser une méthode générique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        public static <T extends Number> void addNumber2(List<T> input,
                List<T> output){
     
            for(T n: input) {
                output.add(n); // ok
            }
        }
    Ainsi, le type générique T implique que les List contiennent des objets héritant de Number, mais que les deux liste soient identique, donc ceci fonctionne parfaitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            List<Integer> list1 = new ArrayList<Integer>();
            List<Integer> list2 = new ArrayList<Integer>();
            addNumbers(list1, list2);
    Tout comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            List<Double> list1 = new ArrayList<Double>();
            List<Double> list2 = new ArrayList<Double>();
            addNumbers(list1, list2);
    Puisque les types sont compatible...


    Par contre l'appel suivant provoquera une erreur de compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            List<Double> list1 = new ArrayList<Double>();
            List<Integer> list2 = new ArrayList<Integer>();
            addNumbers(list1, list2);
    a++

  7. #7
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par adiGuba
    Salut,

    Je pense qu'il s'agit d'une coquille dans l'article
    OK, merci, ça me rassure, je comprends mieux

    Sinon, t'as une idée pour mon pb?

  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
    Ta classe CubeCell c'est quoi exactement ?
    De quel manière elle hérite de AbstractCell ?

    J'ai du mal à comprendre ce que tu veux faire...

    a++

  9. #9
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par adiGuba
    Ta classe CubeCell c'est quoi exactement ?
    De quel manière elle hérite de AbstractCell ?

    J'ai du mal à comprendre ce que tu veux faire...

    a++
    De cette manière...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class AbstractCell<T extends ObjetGeometrique> {
     ...
        public void set(T t) {
            ....
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class CubeCell extends AbstractCell<Cube> {
     ...
        public void set(Cube cube) {
            ....
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class SphereCell extends AbstractCell<Sphere> {
     ...
        public void set(Sphere sphere) {
            ....
        }
    }
    Et ce que je veux faire (sans suppresswarning):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object value = ...
    @SuppressWarnings("unchecked") AbstractCell renderer = new CubeCell();
    if(value instanceof Cube) {
         renderer = cubeRenderer;
         renderer.set((Cube) value);
    } else if(value instanceof Sphere) {
         renderer = sphereRenderer;
         renderer.set((Sphere) value);
    }
    renderer.setBackground(bg);
    En fait, CubeCell et SphereCell sont des AbstractCell paramétrées par le bon type (pour que la méthode set soit déclarée correctement)...

  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
    Ok je vois mieux...


    Il faut que ton renderer soit également du même type (SphereCell pour une Shpere, CubeCell pour un Cube). Il faut donc que la création du renderer soit dans le if/instanceof :

    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
            Object value = ...;
            AbstractCell<? extends ObjetGeometrique> renderer = null;
     
            if(value instanceof Cube) {
                CubeCell cubeCell = new CubeCell();
                cubeCell.set((Cube) value);
                renderer = cubeCell;
            } else if(value instanceof Sphere) {
                SphereCell sphereCell = new SphereCell();
                sphereCell.set((Sphere) value);
                renderer = sphereCell;
            }
            if (renderer != null) {
                renderer.setBackground(bg);
            }
    a++

  11. #11
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Ah bah voilà!
    Je suis bête...

    J'ai essayé plein de trucs, et j'ai pas pensé à appliquer le set() sur le bon objet

    Merci (très) beaucoup!

  12. #12
    Membre expérimenté
    Avatar de RanDomX
    Profil pro
    sans
    Inscrit en
    Mars 2003
    Messages
    579
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Mars 2003
    Messages : 579
    Points : 1 407
    Points
    1 407
    Par défaut
    Il n'y a pas de coquille ds l'article:

    C'est marqué:

    Nous avons bien pris soin de spécifier que les éléments de la liste des résidents sont de tout type héritant de Resident. Cependant comme nous venons de le dire, il est impossible de modifier la liste passée en paramètre. La ligne 6 provoque donc une erreur de compilation.


    Les méthodes génériques arrivent ici à point nommé en déduisant le type à assigner :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    static <T extends Resident> void addResidents(List<T> newComers, List<Resident> residents)
    { 
    for(T n: newComers) { residents.add(n); // pas d’erreur ici. 
    } 
    }
    ici tu précises clairement que T le type paramétré doit etendre Resident. T est nommé est est lui meme un type, que tut peux donc utiliser en tant que tel, pas comme ? qui est un wildcard et donc pas un type...

    E ngros tu restrreinds le scope de T possibles à tous types qui étend Resident, rien de plus, tu assures donc la compatiblité de tes éléments.


    Qu'est ce que tu ne comprends pas ?

  13. #13
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    RanDomX, je pense que l'exemple recopié de la FAQ que j'ai fait sur le premier post est faux...

    Tout simplement parce que ce code:
    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
    import java.util.*;
     
    public class Test {
        static void addElement(List<? extends Number> news, List<Number> num) {
            for(Number n : news) {
                num.add(n);
            }
        }
     
        public static void main(String...args) {
            List<Integer> integers = new ArrayList<Integer>();
            List<Number> numbers = new ArrayList<Number>();
            addElement(integers,numbers);
        }
    }
    compile très bien...
    Et c'est la même chose...

  14. #14
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    RanDomX, faudrait-il corriger cette erreur sur la FAQ, ou tu n'es pas d'accord avec moi?

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 27/04/2015, 23h23
  2. Javascript sur facebook (JBSJ), moi pas comprendre ^^
    Par Nephtys dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 12/03/2009, 11h29
  3. comparaison de chaines - Moi pas comprendre
    Par Laurent68 dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 03/11/2006, 14h49
  4. [C#] Form ShowDialog pas comprendre :p
    Par betaphp dans le forum Windows Forms
    Réponses: 2
    Dernier message: 19/12/2005, 14h37
  5. Réponses: 2
    Dernier message: 21/02/2005, 10h42

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