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 :

[jse5/generics] Méthodes génériques


Sujet :

Langage Java

  1. #1
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    128
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 128
    Points : 353
    Points
    353
    Par défaut [jse5/generics] Méthodes génériques
    Bonjour,

    J'ai un petit problème suite à l'utilisation (abusive) de méthodes génériques pour factoriser du code.

    Je cherche en fait à instancier un objet au sein d'une méthode générique de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private <T extends A> T instanciationSelective(boolean classeA) {
      T unObjet = null;          
      if (classeA)
        unObjet = new A();
      else
        unObjet = new B();
      return unObjet
    }
    avec la classe B héritant de la classe A

    évidemment je vous le donne en mille, le compilo n'arrive pas à piger que unObjet est une instance de A ou de ses sous-classes et me sort deux bonnes grosses erreurs "incompatibles types" (found A required T et found B required T).

    si je caste à l'instanciation, là j'ai le droit à l'habituel warning "unchecked cast".

    Comment se sortir de là sans erreur ni warning ? Pourquoi dans les méthodes génériques la substitution n'est pas faite (alors que dans une classe générique, tout objet de type T aurait accès aux méthodes définies dans A)?

    Merci
    ++
    Développeur / Formateur
    Tutoriels AngularJS / Node.js sur ma chaîne Youtube : http://www.youtube.com/user/DevDuFutur

  2. #2
    Membre expérimenté
    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
    Points : 1 419
    Points
    1 419
    Par défaut
    Le problème :
    1) Tu ne définis pas T. À part le fait de savoir qu'il étend A, on ne sait rien.
    2) on ne sait rien de T, et tu tentes de lui attribuer une instance de A.
    3) on ne sait rien de T, on ne sait rien de B, et tu tentes de lui attribuer une instance de A.

    La solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    private A instanciationSelective(boolean classeA) {
      A unObjet = null;          
      if (classeA)
        unObjet = new A();
      else
        unObjet = new B();
      return unObjet;
    }
    Eh oui, les generics ne sont pas nécessaire dans ce cas ^^

  3. #3
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    128
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 128
    Points : 353
    Points
    353
    Par défaut
    c'est normal que je ne définisse pas T puisqu'il s'agit d'un type générique...

    le code de A et de B dans cet exemple sont très simples :
    class A {}
    class B extends A {}

    Eh oui, les generics ne sont pas nécessaire dans ce cas ^^
    Si quand même ^^ le problème avec ta solution est que le type déclaré de l'instance renvoyée sera toujours A et on ne pourra pas utiliser le comportement de B sans cast (le but d'utiliser les types génériques est justement d'éviter le cast et donc d'éviter de tout le temps vérifier le type à l'execution...

    D'autres idées (si possible avec les génériques à moins qu'une autre solution puisse être aussi propre) ?
    Développeur / Formateur
    Tutoriels AngularJS / Node.js sur ma chaîne Youtube : http://www.youtube.com/user/DevDuFutur

  4. #4
    Membre expérimenté
    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
    Points : 1 419
    Points
    1 419
    Par défaut
    Merci -_- Je sais encore ce qu'est un générique...

    La seule solution envisageable alors est de transmettre la classe à la place d'un booléen comme paramètre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private <T extends A> T instanciationSelective (Class<T> classe)
      throws InstantiationException, IllegalAccessException
    {
      return classe.newInstance();
    }
    Pas d'autre possibilité envisageable, générique ou pas.

  5. #5
    Membre averti
    Inscrit en
    Novembre 2006
    Messages
    128
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 128
    Points : 353
    Points
    353
    Par défaut
    oki ! c'est quand même étonnant quand même qu'il n'y ait pas d'autre solution... en plus, c'est con d'utiliser le class loader pour faire ça puisque le compilo a encore moins de contrôle sur le truc... je sens que ça va caster à l'ancienne !

    c'était pourtant une application très classique des types génériques...

    ++ et merci
    Développeur / Formateur
    Tutoriels AngularJS / Node.js sur ma chaîne Youtube : http://www.youtube.com/user/DevDuFutur

  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,

    Citation Envoyé par palnap Voir le message
    c'était pourtant une application très classique des types génériques...
    Non : ton code n'est pas du tout type-safe !


    Tu as une déclaration comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private <T extends A> T instanciationSelective(boolean classeA)
    Et un code comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    B b1 = instanciationSelective(true);
    B b2 = instanciationSelective(false);
    Le compilateur n'a aucun moyen de vérifier le type de retour de la méthode car celui-ci dépend d'un booléen...
    Il faudrait une analyse du code pour vérifier cela ce que ne fait pas le compilateur (et qu'il ne pourrait pas forcément faire de toute manière).



    Explique un peu plus ce que tu fais car il doit surement y avoir une autre solution. De plus si tu fais des cast en dur autant utiliser deux méthode différente (l'exemple de instanciationSelective() que tu montres n'apporte aucune intérêt).

    a++

Discussions similaires

  1. Réponses: 2
    Dernier message: 07/12/2009, 16h50
  2. Méthode (générique) de récupération de config
    Par je®ome dans le forum Linux
    Réponses: 5
    Dernier message: 06/05/2009, 09h43
  3. Generic : méthodes
    Par Morbo dans le forum Langage
    Réponses: 6
    Dernier message: 30/10/2008, 13h47
  4. Réponses: 10
    Dernier message: 04/03/2008, 15h13
  5. [Generics] Classe générique
    Par norkius dans le forum Langage
    Réponses: 4
    Dernier message: 29/10/2004, 15h57

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