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 :

Listes et generics


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 147
    Par défaut Listes et generics
    Bonjour,

    Un correspondant me signale rencontrer le problème suivant avec mon code :

    Error: (85, 136) java: incompatible types: java.util.List<capture#1 of ? extends jamel.util.Agent> cannot be converted to java.util.List<jamel.models.util.Employer>
    La ligne de code qui pose problème est la suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    final List<Employer> newList = (List<Employer>) this.getSimulation().getSector(sectorName).selectAll();
    Et voilà la déclaration de selectAll() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	 /**
             * Returns a list of all agents of this sector, in a random order.
             * 
             * @return a list of all agents of this sector.
             */
    	List<? extends Agent> selectAll();
    La difficulté semble venir du fait que Agent et Employer sont deux interfaces indépendantes.
    Pourtant, lorsque la liste renvoyée par selectAll() contient des objets qui étendent à la fois Agent et Employer, je n'ai aucun problème.

    Pourquoi mon correspondant rencontre-t-il, lui, dans les mêmes circonstances, ce problème ?
    Comment résoudre cette incompatibilité ?

  2. #2
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Hello,

    Citation Envoyé par sepas Voir le message
    Pourtant, lorsque la liste renvoyée par selectAll() contient des objets qui étendent à la fois Agent et Employer, je n'ai aucun problème.
    Aucun problème, c'est vite dit : Java te fait un énorme warning sur cette ligne. Et il a bien raison. Quel intérêt d'utiliser les génériques si on ne vérifie pas la cohérence de type ?

    Citation Envoyé par sepas Voir le message
    Pourquoi mon correspondant rencontre-t-il, lui, dans les mêmes circonstances, ce problème ?
    Il a certainement configuré son environnement pour que les warnings soient considérés comme des erreurs. C'est ce que font les professionnels.

    Citation Envoyé par sepas Voir le message
    Comment résoudre cette incompatibilité ?
    Il y a plusieurs approches.

    La meilleure est de te demander pourquoi tu fais ça, qui cause un warning évident puisque ça ignore la cohérence de typage, et de réorganiser ton code pour ne faire que du typage cohérent ou bien encadré.

    La seconde est de mettre un suppresswarning sur cette ligne. Après tout il en faut de temps en temps, mais un professionel ne le ferait que dans les bonnes circonstances, c'est à dire pas sur cette ligne.

    La troisième est de convaincre ton correspondant de changer sa conf' pour que les warnings ne soient pas des erreurs.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 147
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Aucun problème, c'est vite dit : Java te fait un énorme warning sur cette ligne.
    Ok, j'avais rajouté @SuppressWarnings("unchecked").
    Si je retire cette annotation, j'ai effectivement un warning :

    Type safety: Unchecked cast from List<capture#1-of ? extends Agent> to List<Employer>
    Mais comment traiter correctement ce warning ? L'objet Sector est construit pour pouvoir contenir tout type d'agents, pas nécessairement de type Employer.

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Dans ce cas,

    - Employer devrait être un sous-type de Agent.

    - Soit
    -- tu prends une List<Agent> ou une List<? extends Agent> et tu travailles avec

    -- tu rends Sector ou sa méthode selectAll() générique pour pouvoir être réglé à renvoyer des Employer et pas juste des Agent. Là tu dis que ça renvoie des Employer. Bon ben comment tu lui as signalé que c'est ça qu'il doit renvoyer et pas un autre type d'agent ? C'est sur ce moyen-là qu'il faut faire jouer les génériques.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 147
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Employer devrait être un sous-type de Agent.
    Ca ne semble pas poser de problème.

    Citation Envoyé par thelvin Voir le message
    tu prends une List<Agent> ou une List<? extends Agent> et tu travailles avec
    Là, je ne te suis pas : que veux-tu dire ?

    Citation Envoyé par thelvin Voir le message
    tu rends Sector ou sa méthode selectAll() générique pour pouvoir être réglé à renvoyer des Employer et pas juste des Agent. Là tu dis que ça renvoie des Employer. Bon ben comment tu lui as signalé que c'est ça qu'il doit renvoyer et pas un autre type d'agent ? C'est sur ce moyen-là qu'il faut faire jouer les génériques.
    Le constructeur de Sector reçoit en argument un doc XML qui contient tous ses paramètres, dont le nom de la classe des agents dont il va être peuplé.
    Donc quand le constructeur a fini son job, le type d'agent du secteur est fixé.
    Comment à partir de là je peut rendre selectAll() générique ?

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Citation Envoyé par sepas Voir le message
    Là, je ne te suis pas : que veux-tu dire ?
    Il pourrait être possible de ne pas avoir besoin de savoir que tes objets sont des Employer, et que juste travailler avec des Agent suffise.
    Employer pourrait par exemple ne pas avoir de méthode publique supplémentaire par rapport à Agent, ou bien tu pourrais ne pas vraiment en avoir besoin.
    Il serait possible aussi que, si tu as bel et bien besoin de ces méthodes, en réalité elles pourraient marcher en les mettant dans Agent, ou bien Agent pourrait être rendue plus générique de sorte que quelque chose de ce genre soit possible.

    Ça pourrait être possible.
    Mais... Peut-être que ça ne l'est pas, pas en faisant du typage simple et strict.
    Disons que ça pourrait être une solution. C'est à voir.
    Ce n'est pas forcément une solution.

    Citation Envoyé par sepas Voir le message
    Le constructeur de Sector reçoit en argument un doc XML qui contient tous ses paramètres, dont le nom de la classe des agents dont il va être peuplé.
    Donc quand le constructeur a fini son job, le type d'agent du secteur est fixé.
    Comment à partir de là je peut rendre selectAll() générique ?
    Bon ben, effectivement le Sector va décider lui-même quelle classe il produit, en fonction du contenu d'un fichier. Du coup la généricité ne peut pas être exprimée de ce côté-là.

    Mais au bout du compte, quand tu t'en sers, tu demandes à recevoir une List<Employer>. Donc tu sais à l'avance que ce Sector-là, il reçoit une configuration qui lui dit de renvoyer des instances de Employer.
    Ça veut dire qu'au moment de sa création, tu pourrais lui passer en paramètre la Employer.class pour lui signaler que c'est ça que tu attends qu'il produise, et qu'il vérifie que la conf' qu'il utilise respecte bien cela.

    Quelque chose de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Sector<E extends Agent> {
     
      public Sector(Document confFile, Class<E> agentClass) {
        readConf();
        checkThatConfProduces(agentClass);
      }
     
      public List<E> selectAll() {
        // ...
      }
     
    }
    qui serait construit ensuite avec :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Sector<Employer> employerSector = new Sector<>(confFile, Employer.class);
    Et derrière il faudrait le récupérer avec quelque chose comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    final List<Employer> newList = this.getSimulation().getEmployerSector(sectorName).selectAll();
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 06/11/2007, 21h05
  2. Stéréotype List et generics java
    Par ptit-lu dans le forum BOUML
    Réponses: 4
    Dernier message: 30/07/2007, 10h11
  3. [Generics] ajouter un élement dans une liste typée
    Par anitshka dans le forum Collection et Stream
    Réponses: 14
    Dernier message: 06/02/2007, 11h04
  4. [Generics][Tableaux][Collections] Tableau liste entiers
    Par MyGoddess dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 04/11/2005, 12h44
  5. [generic] pb création d'une List []
    Par yoplaboom dans le forum Langage
    Réponses: 6
    Dernier message: 08/07/2005, 13h01

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