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 :

Instanciation de générique


Sujet :

Langage Java

  1. #1
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut Instanciation de générique
    Bonjour,

    j'aimerai instancier un type générique un peu de cette facon (sauf que la ca ne marche pas) :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class MaClasse<AImpl extends A> {
        public void function test() {
            AImpl a = AImpl.class.newInstance();
        }
    }

    Je n'arrive pas a trouver d'exemple ou l'on peut faire ca (d'ailleur je ne sais même pas si c'est possible).
    Avez vous une idée ?

    Merci d'avance pour vos réponses.

  2. #2
    Membre Expert
    Avatar de natha
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    2 346
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2006
    Messages : 2 346
    Par défaut
    Tu ne peux pas faire ça. Les génériques disparaissent à la compilation.

    La solution serait de fournir au constructeur de ta classe, une référence de la classe AImpl à instancier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public MaClasse(Class<AImpl> clazz) {
        //...
    }
    Ainsi tu pourras faire newInstance() sur clazz.

  3. #3
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Dommage...

    J'ai commencé a regardé si on pouvait pas faire ca par introspection (j'ai vu ce genre de méthode "TypeVariable.getGenericDeclaration() " qui me laisse un peu d'espoir) mais je n'ai maleureusement pas énnormément de temps pour approfondir pour le moment

    Si quelqu'un a une autre idée...

    En tout cas merci natha, je vais faire comme tu as dis pour le moment (quitte a changer par la suite)

    Edit: je passe le post en résolu car j'ai un moyen de contournement mais j'aimerai vraiment faire autrement. (donc toutes les idées sont encore les bienvenues)

  4. #4
    Membre Expert

    Homme Profil pro
    Architecte logiciel
    Inscrit en
    Novembre 2006
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte logiciel
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 252
    Par défaut
    Pas possible, même par introspection.

    Le "TypeVariable.getGenericDeclaration() " que tu as vu, te permet de récupérer le type de la généricité tel que déclaré comme là:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     public class TestType {
      List<String> aList;
     }
     
      System.out.println( TestType .class.getField("aList").getGenericType() );
    Ca te retourne String.

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

    Citation Envoyé par Tommy31 Voir le message
    Le "TypeVariable.getGenericDeclaration() " que tu as vu, te permet de récupérer le type de la généricité tel que déclaré comme là:
    +1



    En fait il faut comprendre que via la reflection on n'a accès qu'aux informations contenu dans le code de la classe. Par exemple si on a ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public class MaClasse<T extends Number> {
    	private List<T> list;
    }
    On peut retrouver le T et savoir qu'il hérite de Number, mais on ne pourra pas déterminer si une instance en particulier utilise des Double ou des Integer...


    a++

  6. #6
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Pour information, pourquoi souhaites-tu utiliser cela ? (je n'en ai jamais eu l'utilité comme ça)

  7. #7
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Je vais essayer de l'expliquer par l'exemple en simplifiant pas mal.
    Il s'agit de la lecture de différent type de référentiel.
    Ma classe générique s'occupe des traitement comment de tous mes référentiels et ensuite elle est étendu autant de fois que nécessaire (en fonction des différrent référentiels lire

    Code Java : 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
    public abstract class ClasseGenerique<RefImpl extends Ref> {
      /** Cette méthode créer un objet de type RefImpl et le peuple avant de le retourner */
      public RefImpl getReferentiel() {
        // Creation du référentiel et Traitement commun lors de la lecture du référentiel
        ...
        // Appel des traitement spécifique au référentiel
        traitementSpecifique();
      }
      /** Traitement spécifique a ce type de référentiel */
      public abstract void traitementSpecifique();
    }
     
    public ClasseSpecifique extends ClasseGenerique<MonImplementationDuReferentiel> {
      public void traitementSpecifique() {
        // Traitement spécifique lors de la lecture du référentiel
        ...
      }
    }

    Dans l'idée, il s'agit plus ou moins du pattern factory mais un peu adapté a mes besoins (ca en fera certainement bondir plus d'un mais c'est pas évident de se faire comprendre)

  8. #8
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Par défaut
    Il y a la méthode là, mais bon (ça permet au moins de gérer plus finement l'instanciation dans les classes filles)


    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
    public abstract class ClasseGenerique<RefImpl extends Ref> {
      protected abstract RefImpl getInstance();
     
      public RefImpl getReferentiel() {
        RefImpl imp =  getInstance();
        ...
        // Appel des traitement spécifique au référentiel
        traitementSpecifique();
      }
      /** Traitement spécifique a ce type de référentiel */
      public abstract void traitementSpecifique();
    }
     
    public ClasseSpecifique extends ClasseGenerique<MonImplementationDuReferentiel> {
      protected MonImplementationDuReferentiel getInstance() {
         return new MonImplementationDuReferentiel ();
      }
     
      public void traitementSpecifique() {
        // Traitement spécifique lors de la lecture du référentiel
        ...
      }
    }

  9. #9
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    C'est effectivement une autre facon de faire (qui faut l'avouer, a ses avantages).
    Ceci dit, dommage qu'on ne puisse pas faire directement comme je pensais le faire au début, ca simplifirait ce genre de code...

    Edit : je viens de me rendre compte que je ne suis pas le seul a avoir ce genre de problèmatique... (http://wiki.apache.org/tapestry/Tape...ectWithObjects) Quand on voit l'implémentation de leur première classe, on retrouve la première solution )

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


    La solution a été donné par natha :
    Citation Envoyé par natha Voir le message
    La solution serait de fournir au constructeur de ta classe, une référence de la classe AImpl à instancier.
    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
    abstract class ClasseGenerique<R extends Ref> {
     
    	/** Type generics associé à la classe */
    	private final Class<R> rType;
     
    	/** Constructeur */
    	public ClasseGenerique(Class<R> type) {
    		if (type==null) {
    			throw new NullPointerException("type is null");
    		}
    		this.rType = type;
    	}
     
    	/**
             * Méthode de création d'une instance
             * (le type R doit posséder un constructeur vide)
             * @return Une nouvelle instance de R
             * @throws RuntimeException en cas d'erreur lors de l'instanciation
             */
    	public R newInstance() {
    		try {
    			return this.rType.newInstance();
    		} catch (RuntimeException e) {
    			// On remonte la runtimeexception tel quel
    			throw e;
    		} catch (Exception e) {
    			// On englobe l'exception dans une Runtime
    			throw new RuntimeException(e);
    		}
    	}
    }
    Seul bémol il faut passer le type en paramètre lors de la création...


    a++

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 16/02/2013, 00h27
  2. Templates : Instancier un type générique
    Par la_urre dans le forum C++
    Réponses: 5
    Dernier message: 09/05/2010, 00h44
  3. Classes génériques - problème d'instanciation
    Par aigleborgne dans le forum C#
    Réponses: 2
    Dernier message: 26/03/2010, 16h58
  4. Réponses: 2
    Dernier message: 25/12/2008, 21h51
  5. Réponses: 3
    Dernier message: 12/06/2008, 17h05

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