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 :

Mettre une valeur dans une liste générique List<? extends AbstractResult>


Sujet :

Langage Java

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 123
    Points : 137
    Points
    137
    Par défaut Mettre une valeur dans une liste générique List<? extends AbstractResult>
    Bonjour à tous,

    J'ai une liste de données que je dois avoir brutes ou ordonnées. Pour cela, j'ai 3 classes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    abstract class AbstractResult {}
    class Result extends AbstractResult{}
    class OrderResult extends AbstractResult{}
    J'écris une méthode générique qui pourra remplire une liste avec les données avec comme paramètre un boolean pour dire quel type de list on veut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private List<? extends AbstractResult> createGenericResults(boolean ordered) {
    	// Create result type
    	List<? extends AbstractResult> result;
    	if(ordered) {
    		result = new ArrayList<OrderResult>();
    	} else {
    		result = new ArrayList<Result>();
    	}
    }
    Le problème, se situe dans la méthode générique, lorsque je tente de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    result.add(new OrderResult(a, b, c, d));
    Je reçois le message suivant de la part du compilateur:
    The method add(capture#5-of ? extends AbstractResult) in the type List<capture#5-of ? extends AbstractResult> is not applicable for the arguments (OrderResult)

    Comment puis-je fair pour qu'il accepte de remplir ma liste de façon générique ???

    Un grand merci d'avance.

  2. #2
    Membre confirmé Avatar de freddou17
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2013
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2013
    Messages : 341
    Points : 566
    Points
    566
    Par défaut
    Bonjour,

    as-tu essayer d'initialiser ta liste comme ci-dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    List<AbstractResult> result = new ArrayList<AbstractResult>();
    if(ordered) {
    		result.add(new OrderResult(a, b, c, d));
    	} else {
    		result.add(new Result(a, b, c, d));
    	}
    Tu pourras récupérer les objets et les caster selon le bon type vue qu'ils extendent la même classe abstraite.
    Ceci devrait marcher...

    Tiens nous au courant ++

  3. #3
    Membre chevronné Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2008
    Messages
    1 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 501
    Points : 2 120
    Points
    2 120
    Par défaut
    salut,
    en effet
    il est impossible pour lui de savoir si ton ajout est de type effectif ou inconnu.
    en principe les type Wilcard sont verrouillés pour l´insertion et ne sont que Readonly.

    pour que cela puisse marcher dans ton exemple,
    il faut plutot faire ce genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      private List<? super AbstractResult> createGenericResults(boolean ordered) {
    	// Create result type
    	List<? extends AbstractResult> result;
    	if(ordered) {
    		result = new ArrayList<OrderResult>();
    	} else {
    		result = new ArrayList<Result>();
    	}
    }
    Eric

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 566
    Points : 21 635
    Points
    21 635
    Par défaut
    Non jeffray, ce n'est pas comme ça que ça marche.

    Les wildcards en extends sont read-only, c'est la seule chose intéressante. Ça n'a aucun sens d'utiliser un wilcard en super à la place.

  5. #5
    Modérateur
    Avatar de Alkhan
    Homme Profil pro
    ingénieur full stack
    Inscrit en
    Octobre 2006
    Messages
    1 232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : ingénieur full stack

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 232
    Points : 2 061
    Points
    2 061
    Par défaut
    Citation Envoyé par VonDriguen Voir le message
    Bonjour à tous,
    J'ai une liste de données que je dois avoir brutes ou ordonnées.
    Je suis pas sur de comprendre se que tu veux faire, mais selon se que tu écris, c'est le contenu de chaque élément qui est ordonnée pas la liste, on est bien d'accord ?
    De plus, si tu tente de faire une liste générique de cette façon tu ne bloquera pas le type de données que tu pourra mettre dedans. En effet le résultat sera au final que tu pourra mettre a la fois des instances de "OrderResult" et des instances de "Result" dans une même liste.
    Que souhaites tu faire réellement ?

    Citation Envoyé par jeffray03 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      private List<? super AbstractResult> createGenericResults(boolean ordered) {
    	// Create result type
    	List<? extends AbstractResult> result;
    	if(ordered) {
    		result = new ArrayList<OrderResult>();
    	} else {
    		result = new ArrayList<Result>();
    	}
    }
    Ca compilera mais ca reviendrais a écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	private List<AbstractResult> createGenericResults(boolean ordered) {
    		// Create result type
    		List<? extends AbstractResult> result;
    		result = new ArrayList<AbstractResult>();
    		.....
    	}

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 123
    Points : 137
    Points
    137
    Par défaut
    Merci pour vos réponses.

    Effectivement, le code de jeffray03 ne fonctionne malheureusement pas non plus.

    Pour être plus claire, je voulais générer, depuis le même input, une liste comprenant SOIT uniquement des Result, SOIT uniquement des OrderResult. Pas les deux. La solution de freddou17 risquait donc également de poser problème

    J'ai donc fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private List<? extends AbstractResult> createGenericResults(final boolean ordered) {
    	// Create result type
    	List<Result> results = new ArrayList<Result>();
    	List<OrderResult> oResults = new ArrayList<OrderResult>();
    }
    Et en fonction du boolean, je rempli l'une ou l'autre liste et je renvoie celle qui n'est pas vide.

    Mais si quelqu'un a une solution plus générique, je suis preneur...

  7. #7
    Membre confirmé Avatar de freddou17
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2013
    Messages
    341
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2013
    Messages : 341
    Points : 566
    Points
    566
    Par défaut
    Citation Envoyé par VonDriguen Voir le message
    Merci pour vos réponses.

    Effectivement, le code de jeffray03 ne fonctionne malheureusement pas non plus.

    Pour être plus claire, je voulais générer, depuis le même input, une liste comprenant SOIT uniquement des Result, SOIT uniquement des OrderResult. Pas les deux. La solution de freddou17 risquait donc également de poser problème

    J'ai donc fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private List<? extends AbstractResult> createGenericResults(final boolean ordered) {
    	// Create result type
    	List<Result> results = new ArrayList<Result>();
    	List<OrderResult> oResults = new ArrayList<OrderResult>();
    }
    Et en fonction du boolean, je rempli l'une ou l'autre liste et je renvoie celle qui n'est pas vide.

    Mais si quelqu'un a une solution plus générique, je suis preneur...
    Pourquoi pas!! mais j'aimerais bien la suite de ton code stp (l'utilisation et le remplissage de la liste) car je n'arrive pas à voir comment tu vas distinguer quelle liste (avec quel typage) tu as renvoyé sans retester ta variable orderer.
    En tout cas cool que tu sois débloqué.

    ++

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 123
    Points : 137
    Points
    137
    Par défaut
    Citation Envoyé par freddou17 Voir le message
    Pourquoi pas!! mais j'aimerais bien la suite de ton code stp (l'utilisation et le remplissage de la liste) car je n'arrive pas à voir comment tu vas distinguer quelle liste (avec quel typage) tu as renvoyé sans retester ta variable orderer.
    En tout cas cool que tu sois débloqué.

    ++
    Voici le code complet. S'il faut des explications supplémentaires, pas de problème.
    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    private List<? extends AbstractResult> createGenericResults(final boolean ordered) {
    	// Create result type
    	List<Result> results = new ArrayList<Result>();
    	List<OrderResult> oResults = new ArrayList<OrderResult>();
     
    	// Read file and create objects
    	File file = new File("files/Data.csv");
    	try {
    		Scanner reader = new Scanner(file);
    		// Read by line
    		while(reader.hasNextLine()) {
    			String line = reader.nextLine();
    			Scanner lineReader = new Scanner(line);
    			// Delimit and fill the list
    			lineReader.useDelimiter(";");
    			if(ordered) {
    				oResults.add(new OrderResult(lineReader.next(),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next())));
    			} else {
    				results.add(new Result(lineReader.next(),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next()),
    								Integer.valueOf(lineReader.next())));
    			}
    		}
    	reader.close();
    	} catch (FileNotFoundException e) {
    		throw new RuntimeException("Problem to scan file " + e);
    	}
     
    	// Return result type
    	if(ordered) {
    		return oResults;
    	}
    	return results;
    }
    Pour le return, j'avais écris ça au début
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Return result type
    if(!oResults.isEmpty()) {
    	return oResults;
    }
    return results;
    Mais je me suis rendu compte que ça risquait de poser problème. Alors j'ai mis le boolean en final et je le test de nouveau.

    Si quelqu'un voit une amélioration à effectuer, je suis preneur

  9. #9
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 566
    Points : 21 635
    Points
    21 635
    Par défaut
    Pour un besoin pareil la généricité est un non-sens, puisque c'est le boolean ordered qui détermine le typage de la liste. Il n'y a donc pas de généricité. Il faut une méthode pour un cas et une méthode pour l'autre cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private List<Result> createResults() {
      //
    }
     
    private List<OrderResult> createOrderResults() {
      //
    }
    Par contre, les deux ayant beaucoup de code en commun, on peut les faire passer par une ou plusieurs méthodes qui, elles, seront génériques. Ici ça marche en n'en mettant qu'une :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    private <T extends AbstractResult> List<T> createGenericResults(ResultFactory<T> factory) {
      List<T> results = new ArrayList<T>();
     
      // Read file and create objects
      File file = new File("files/Data.csv");
      try(Scanner reader = new Scanner(file)) {
        // Read by line
        while(reader.hasNextLine()) {
          String line = reader.nextLine();
          Scanner lineReader = new Scanner(line);
          // Delimit and fill the list
          lineReader.useDelimiter(";");
     
          T result = factory.newResult(lineReader.next(), lineReader.nextInt());
          results.add(result);
        }
        return results;
      } catch (FileNotFoundException e) {
        throw new RuntimeException(e.getMessage(), e);
      }
    }
     
    private List<Result> createResults() {
      return createGenericResults(DEFAULT_FACTORY);
    }
     
    private List<OrderResult> createOrderResults() {
      return createGenericResults(ORDER_FACTORY);
    }
     
    private interface ResultFactory<T extends AbstractResult> {
      T newResult(String s, int i);
    }
     
    private static final ResultFactory<Result> DEFAULT_FACTORY = new ResultFactory<Result>() {
      @Override
      Result newResult(String s, int i) {
        return new Result(s, i);
      }
    };
     
    private static final ResultFactory<OrderResult> ORDER_FACTORY = new ResultFactory<OrderResult>() {
      @Override
      OrderResult newResult(String s, int i) {
        return new OrderResult(s, i);
      }
    };

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 123
    Points : 137
    Points
    137
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Pour un besoin pareil la généricité est un non-sens, puisque c'est le boolean ordered qui détermine le typage de la liste. Il n'y a donc pas de généricité. Il faut une méthode pour un cas et une méthode pour l'autre cas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private List<Result> createResults() {
      //
    }
     
    private List<OrderResult> createOrderResults() {
      //
    }
    Par contre, les deux ayant beaucoup de code en commun, on peut les faire passer par une ou plusieurs méthodes qui, elles, seront génériques. Ici ça marche en n'en mettant qu'une :

    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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    private <T extends AbstractResult> List<T> createGenericResults(ResultFactory<T> factory) {
      List<T> results = new ArrayList<T>();
     
      // Read file and create objects
      File file = new File("files/Data.csv");
      try(Scanner reader = new Scanner(file)) {
        // Read by line
        while(reader.hasNextLine()) {
          String line = reader.nextLine();
          Scanner lineReader = new Scanner(line);
          // Delimit and fill the list
          lineReader.useDelimiter(";");
     
          T result = factory.newResult(lineReader.next(), lineReader.nextInt());
          results.add(result);
        }
        return results;
      } catch (FileNotFoundException e) {
        throw new RuntimeException(e.getMessage(), e);
      }
    }
     
    private List<Result> createResults() {
      return createGenericResults(DEFAULT_FACTORY);
    }
     
    private List<OrderResult> createOrderResults() {
      return createGenericResults(ORDER_FACTORY);
    }
     
    private interface ResultFactory<T extends AbstractResult> {
      T newResult(String s, int i);
    }
     
    private static final ResultFactory<Result> DEFAULT_FACTORY = new ResultFactory<Result>() {
      @Override
      Result newResult(String s, int i) {
        return new Result(s, i);
      }
    };
     
    private static final ResultFactory<OrderResult> ORDER_FACTORY = new ResultFactory<OrderResult>() {
      @Override
      OrderResult newResult(String s, int i) {
        return new OrderResult(s, i);
      }
    };
    De fait ! J'avais mal construit mon code...

    Merci

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 13/04/2015, 11h17
  2. Mettre la valeur d'une combobox dans une feuille Excel
    Par biche1 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 23/10/2008, 13h56
  3. Recherche une valeur d'une cellule dans une colonne d'une autre feuille
    Par kourria dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/06/2007, 13h48
  4. Mettre une valeur d'une table dans une variable
    Par Raphou96 dans le forum Access
    Réponses: 5
    Dernier message: 06/02/2006, 15h19
  5. Mettre la valeur d'une table dans une CString
    Par Lucier dans le forum MFC
    Réponses: 29
    Dernier message: 26/11/2004, 16h04

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