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

avec Java Discussion :

Instantiation générique dans une classe paramétrée


Sujet :

avec Java

  1. #1
    Membre habitué
    Inscrit en
    Octobre 2006
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 200
    Points : 149
    Points
    149
    Par défaut Instantiation générique dans une classe paramétrée
    Bonjour à tous,

    Alors voilà j'ai un petit problème de généricité... Je ne sais pas comment contourner le problème et j'aurai souhaité avoir un maximum d'avis sur le sujet.

    Voilà un code d'exemple de ce que je cherche à faire :

    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
    public abstract class AToto {
     
    	protected final String str;
    	protected final int i;
     
    	public AToto(String str, int i) {
    		this.str = str;
    		this.i = i;
    	}
    }
    public class DefaultToto extends AToto {
     
    	public DefaultToto (String str, int i) {
    		super(str, i);
    	}
    }
    public class AnotherTotoImpl extends AToto {
     
    	public AnotherTotoImpl (String str, int i) {
    		super(str, i);
    	}
    }
    public class TotoManager<T extends AToto> {
     
    	private final List<T> list;
     
    	public TotoManager(String str, int i) {
    		list = new ArrayList<T>();
    		T toto = new T(str, i);
    		list.add(toto);
    	}
    }
     
    public static void main(String[] args) {
    	TotoManager<DefautToto> defaultTotoManager = new TotoManager<DefaultToto>("Test", 0);
    	TotoManager<DefautToto> anotherTotoImplManager = new TotoManager<AnotherTotoImpl>("AntoherTest", 42);
    }
    Et je bloque sur cette instruction dans la classe TotoManager :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T toto = new T(str, i);
    Une idée ?

    Merci d'avance à tous !

  2. #2
    Membre averti Avatar de toutgrego
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mai 2013
    Messages
    217
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2013
    Messages : 217
    Points : 350
    Points
    350
    Par défaut
    Je ne pense pas que tu puisses instancier T
    F*ck it ! Do it !

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    Bonjour,

    Il n'est pas possible d'instancier un générique car toutes les informations génériques ne sont pas visibles à l'exécution. Les génériques sont juste utilisés pour la compilation (vérifier que les bon type est passé au bon endroit).

    C'est comme si à l'exécution ton code avait cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class TotoManager {
     
    	private final List list;
     
    	public TotoManager(String str, int i) {
    		list = new ArrayList();
    		// T toto = new T(str, i); je retire cette ligne qui ne peut pas être transformée...
    		list.add(toto);
    	}
    }
    1ère solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class TotoManager1<T extends AToto> {
     
    		private final List<T> list;
     
    		public TotoManager1(T toto) {
    			list = new ArrayList<T>();
    			list.add(toto);
    		}
    	}
     
    // utilisation 
    TotoManager1<DefaultToto> defaultTotoManager1 = new TotoManager1<DefaultToto>(new DefaultToto("Test", 0));
    2ème solution :
    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
    public class TotoManager2<T extends AToto> {
     
    		private final List<T> list;
     
    		public TotoManager2(String str, int i, Class<T> typeOfToto) {
    			list = new ArrayList<T>();
    			Constructor<?> constructor = typeOfToto.getConstructors()[0];
    			try {
    				T toto = (T) constructor.newInstance(str, i);
    				list.add(toto);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    	}
     
    // Utilisation 
    TotoManager2<DefaultToto> defaultTotoManager2 = new TotoManager2<DefaultToto>("Test", 0, DefaultToto.class);
    Si possible je préfère de loin la première qui implique moins de génériques et est plus orientée objet.

    Romain.

  4. #4
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Dans certains cas la solution de la factory est plus pratique :

    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
    interface TotoFactory<T extends AToto> {
      T newToto(String str, int i);
    }
     
    public class TotoManager<T extends AToto> {
     
      private final List<T> list;
      private final TotoFactory<T> factory;
     
      public TotoManager(TotoFactory<T> factory, String str, int i) {
        list = new ArrayList<T>();
        this.factory = factory;
     
        T toto = factory.newToto(str, i);
        list.add(toto);
      }
    }
     
    public class DefaultToto extends AToto {
      public DefaultToto (String str, int i) {
        super(str, i);
      }
     
      public static TotoFactory<DefaultToto> factory() {
        return new TotoFactory<DefaultToto>() {
          DefaultToto newToto(String str, int i) {
            return new DefaultToto(str, i);
          }
        }
      }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public static void main(String[] args) {
      TotoManager<DefautToto> defaultTotoManager = new TotoManager<>(DefaultToto.factory(), "Test", 0);
    }
    Mais cela oblige à prévoir une factory avec chaque classe Toto, c'est assez contraignant.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    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 thelvin Voir le message
    Dans certains cas la solution de la factory est plus pratique
    +1 pour la factory, ce qui est à mon sens la solution la plus propre.

    Car rien ne garantie que toutes les classes descendant de AToto auront obligatoirement un constructeur prenant deux paramètres (String,int)...


    a++

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 394
    Points : 639
    Points
    639
    Par défaut
    La solution avec la factory ne me semble pas plus propre que la première solution que j'ai présentée car elle couple toujours TotoManager avec les propriétés internes de Toto. Tu es obligé de passer tous les paramètres pour construire Toto en paramètre de TotoManager ( sans compter que l'interface de la factory implique que Toto est toujours construit à partir d'un int et d'un String : T newToto(String str, int i); ).

    Construire Toto en dehors de TotoManager permet de ne pas lier TotoManager aux propriétés internes de Toto.

    Romain.

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Exact, sauf que je pense que l'idée implicité était, vu la présence de a liste, que le manager crée les T à la demande ... Si effectivement il peux se contenter de stocker ce qu'on lui passe, c'est le plus propre.

  8. #8
    Membre habitué
    Inscrit en
    Octobre 2006
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 200
    Points : 149
    Points
    149
    Par défaut
    Merci à tous pour ces réponses !

    Bon il s'avère qu'au final ma conception était mauvaise et en la revoyant je n'ai plus eu besoin de ça.

    Ceci dit merci pour toutes vos réponses, cela m'a permis d'apprendre des choses.

    Dans mon cas la solution de la factory aurait effectivement été la plus pratique (et un pattern très utilisé en entreprise il me semble).

    En fait c'est surtout que je voulais avoir une méthode qui instancie bon type de Toto dans mon manager et me le revoie mais bon... Je n'en ai rien fait au final (enfin j'en ai fait quelque chose quand même puisque je me coucherais moins bête ce soir ! )

    Merci quand même à tous !

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 20/06/2013, 18h07
  2. Membre générique dans une classe ("member template")
    Par damien.flament dans le forum Langage
    Réponses: 13
    Dernier message: 26/08/2010, 07h43
  3. Réponses: 2
    Dernier message: 07/12/2009, 16h50
  4. ClassCastException dans une classe générique
    Par lion13 dans le forum Langage
    Réponses: 2
    Dernier message: 07/05/2008, 19h35
  5. Réponses: 4
    Dernier message: 23/04/2008, 17h11

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