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 :

Notation avec Generic


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Inscrit en
    Mai 2002
    Messages
    328
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Mai 2002
    Messages : 328
    Par défaut Notation avec Generic
    Une question existentielle, il y a t'il une utilité à écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<? extends ITruc> getTrucs()
    au lieu de :

    Merci !
    Toine

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


    Si ca existe c'est qu'il y a bien une raison.

    Pour l'explication et pour plus de clarté je vais utiliser Number à la place de ITruc. Pour rappel Number est la classe parente des types numériques de base (Integer, Float, Double, ...).


    Quelques exemples de listes paramétré
    • List<Number> est une liste de Number. Tu peux donc y mettre n'importe quels "Number" y compris les classes filles. Par contre ces dernières seront vu en tant que Number...
    • List<Integer> est une liste d'Integer, et tu ne peux y mettre que des Integer (puisqu'il n'existe pas de classes filles).
    • List<Double> est une liste de Double, et tu ne peux y mettre que des Double (puisqu'il n'existe pas de classes filles).


    Ces trois listes sont totalement incompatible et tu ne peux pas faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<Integer> integerList = new ArrayList<Integer>();
    List<Number> numberList = integerList; // ERREUR (même avec un cast)
    La raison est simple, car si c'était possible tu pourrais faire ceci par la suite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    numberList.add(new Double(0.0)); // On ajoute un Double dans une List<Number>, ce qui est tout à fait correct
    Mais du coup cela reviendrait à mettre un Double dans une List<Integer> ce qui serait incorrect !


    Pourtant il peut y avoir de nombreux cas où l'on pourrait avoir besoin de faire cela.
    Par exemple si on code une méthode qui calculerait la somme des Number via la méthode doubleValue() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	public double sum(List<Number> numbers) {
    		double sum = 0.0;
    		for (Number n : numbers) {
    			sum += n.doubleValue();
    		}
    		return sum;
    	}
    On ne peut pas utiliser cette méthode avec une List<Integer> ou une List<Double> et il faut la réécrire



    C'est là que les wilcards entre en jeu (? extends ou ? super).
    Avec les wilcards on ne connait pas le type exact du paramétrage, mais on a simplement une information sur son type.


    • List<? extends Number> signifie que tu utilises une List paramétrée avec un type héritant de Number (ou Number lui même). Ainsi ce pourrait être une List<Number>, une List<Integer>, une List<Double> ou autres...

      Du coup tu peux faire ceci sans problème :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      List<Integer> integerList = new ArrayList<Integer>();
      List<? extends Number> numberList = integerList; // OK
      En contrepartie, tu ne peux pas utiliser les méthodes paramétré comme add(T), car tu ignores complètement le type réel de T. Cela permet justement d'éviter d'ajouter un Double dans une liste d'Integer

      Par contre tu peux très bien utiliser les méthodes qui n'utilises pas de type paramétré ou qui se contente de le renvoyer, comme T get(int) ou Iterator<T> iterator(), et dans ce cas T sera supposé à Number. C'est correct puisque tu sais que T est forcément un type fils de Number (ou lui-même).

      Bref en quelques sortes tu n'as accès qu'aux méthodes paramétrés "de lecture", et donc la méthode sum() peut se transformer comme ceci :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      	public double sum(List<? extends Number> numbers) {
      		double sum = 0.0;
      		for (Number n : numbers) { // parcours via Iterator<? extends Number>
      			sum += n.doubleValue();
      		}
      		return sum;
      	}
      Elle est désormais utilisable avec toutes les List<T> paramétré avec un type fils de Number



    • A l'inverse, List<? super Number> signifie que tu utilises une List paramétrée avec un type parent de Number (ou d'une interface implémenté par Number). Dans ce cas précis ce pourrait être List<Number>, List<Serializable> ou List<Object>.

      Ici c'est l'inverse, tu ne peux pas utiliser les méthodes renvoyant T car tu ignores son type réel et que cela peut être un type parent. Par contre tu peux utiliser les méthodes utilisant T en paramétre car tu sais qu'en utilisant un Number tu utilises forcément un type fils de T...

      Tu as le droits de faire add(new Integer(0)) mais pas Number n = get(0) car tu n'est pas sûr de recevoir un Number...


      Ce cas est surement moins utile, et je pense que le meilleur exemple vient de la méthode Collections.addAll() :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      public static <T> boolean addAll(Collection<? super T> c, T... elements) {
      On ajoute des objets de type T dans une collection acceptant des types T (bref une collection paramétré avec T ou un parent).



    En fait les wildcards sont assez puissant car il permet de rajouter plein de contraintes

    J'espère avoir été clair...

    a++

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Euh... impec' Même moi, j'ai enfin compris

    Par contre, une typo : au dernier point de la liste, tu écris
    A l'inverse, List<? extends Number> signifie que ...
    Au lieu de
    A l'inverse, List<? super Number> signifie que ...
    Cela corrigé, direction la FAQ ?

  4. #4
    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 dingoth Voir le message
    Par contre, une typo : au dernier point de la liste, tu écris (...)
    corrigé

    Citation Envoyé par dingoth Voir le message
    Cela corrigé, direction la FAQ ?
    Oui cela pourrait être pas mal dans la FAQ (les Generics pourraient avoir une FAQ pour eux tous seul )

    a++

  5. #5
    Membre éclairé

    Inscrit en
    Mai 2002
    Messages
    328
    Détails du profil
    Informations personnelles :
    Âge : 45

    Informations forums :
    Inscription : Mai 2002
    Messages : 328
    Par défaut
    je comprends mieux en effet, c'est tout à fait logique...

    par contre, l'écriture devient très très lourde

    J'aurai tendance à penser que pour les arguments de méthodes, il vaut mieux utiliser le wildcard pour quelle soit le plus utilisable possible.

    Mais peut être plutôt renvoyé le type plus précis en retour ?

    Qu'en penses-tu ?

    Toine

  6. #6
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Je pense qu'il faut lire d'urgence Simplyfing Java Generics by Eliminating Wildcards.

    Il arrive qu'elles soient utiles, mais en général, non. Quand je suis obligé de les employer, je me dis que j'ai mal fait ma conception quelque part. (mais je les utilise quand même, en attendant d'avoir de meilleures idées).

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

Discussions similaires

  1. Notation avec un @
    Par Hitomi_Kay dans le forum Langage
    Réponses: 2
    Dernier message: 03/08/2009, 16h12
  2. Problème avec generic et appel de méthode
    Par NiamorH dans le forum C#
    Réponses: 10
    Dernier message: 31/10/2008, 19h52
  3. Implementation méthode avec generics
    Par hhhelea dans le forum Langage
    Réponses: 1
    Dernier message: 12/06/2008, 14h47
  4. Créer un système de notation avec des étoiles
    Par babafredo dans le forum ASP
    Réponses: 2
    Dernier message: 02/04/2008, 15h06
  5. probleme avec generic host process for win32 services
    Par thesorrow dans le forum Windows XP
    Réponses: 2
    Dernier message: 15/03/2007, 10h29

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