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 :

Utilisation des generics


Sujet :

Langage Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut Utilisation des generics
    Bonjour a tous,

    je cherche à créer une structuration de class manipulant des objets qui peuvent être des doubles ou des complexes.

    Afin de ne pas écrire plusieurs fois les class Point2D, Point3D, vector, matrix... qui manipule soit des doubles soit des complexes j’aimerai utiliser les generics.

    J'ai donc créé des class (Point2D, Point3D, vector, matrix...) manipulant des :
    MyNumber<>

    MyDouble et MyComplex sont des MyNumber<>

    Or j'ai un problème à la compilation comme définie en suivant:

    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
    public interface Numeric<Type> extends Comparable<Type>{
    	public abstract Type atan2(Type v);
    	public abstract Type atan2(double d);
    	public abstract Type sin();
    	public abstract Type sinh();
    	public abstract Type cos();
    	public abstract Type cosh();
    	public abstract Type tan();
    	public abstract Type add(Type v);
    	public abstract Type add(double d);
    	public abstract Type sub(Type v);
    	public abstract Type sub(double d);
    	public abstract Type cube();
    	public abstract Type sqrt();
    ...
    }
    
    public abstract class MyNumber<T> extends Number implements Numeric<T>{...}
    public class MyDouble extends MyNumber<MyDouble> {...}
    public class MyComplex extends MyNumber<MyComplex> {...}
    
    
    public class Triedre<Type extends MyNumber<Type>>{
    ...
    	private Type a;
    	private Type b;
    	private Type c;
    	
    	public Triedre(Type a, Type b, Type c) {
    		this.a = a;
    		this.b = b;
    		this.c = c;
    	}
    
    	public Triedre(double a, double b, double c) {
    		this.a = new MyDouble(a); // erreur de compilation
    		this.b = new MyDouble(b); // erreur de compilation
    		this.c = new MyDouble(c); // erreur de compilation
    	}
    ...
    }
    en résumé :
    - MyDouble est de type "MyNumber<MyDouble>"
    - le type "Type" dans la class Triedre est de type "MyNumber<Type>"

    comment faire en sorte que les types soit compatible?

    Merci d'avance pour votre support.
    Sébastien.

  2. #2
    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
    Une double est un double, il n'a pas besoin de paramètre et ne peut donc pas avoir de paramètre. MyDouble doit être de type MyDouble sans paramètre.
    De même MyComplex ne doit pas avoir de paramètre.

    Les deux doivent répondre à une interface commune pour addition, etc. Donc interface MyNumber, implémentée par les deux. Mais il va lui falloir un paramètre.

    Parce que, pour l'addition, supposons que ça ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface MyNumber {
      MyNumber add(MyNumber other);
    }
    Du coup MyDouble ressemblera à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public class MyDouble implements MyNumber {
      double value;
      MyDouble add(MyNumber other) {
        double newValue = this.value + other./* ? là on peut rien faire de MyNumber other*/;
      }
    }
    Ça ne va pas. MyDouble.add() doit prendre des MyDouble en paramètre et donner des MyDouble en sortie.

    Comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public interface MyNumber<T extends MyNumber<T>> {
      T add(T other);
    }
     
    public class MyDouble implements MyNumber<MyDouble> {
      double value;
      MyDouble add(MyDouble other) {
        double newValue = this.value + other.value;
     
        MyDouble newDouble = new MyDouble();
        newDouble.value = newValue;
        return newDouble;
      }
    }
    Et voilà.

    Pour les rendre comparables, ajouter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface MyNumber<T extends MyNumber<T>> extends Comparable<T> {
      ...
    }
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Bonsoir thelvin,

    Je suis d'accord avec toi et je pense que ce que j'ai posté dans mon premier message répond à se que tu dis.

    Toutefois, j'ai un problème lorsque je veux utiliser MyDouble et MyComplex dans une class utilisant le père de ses deux class (MyNumber<T>).

    Soit le type "Type" qui extends "MyNumber<Type>"

    pourquoi n'est il pas possible de faire ce qui suit?
    Type a = new MyDouble();

    Or MyDouble est bien du type MyNumber<T>

  4. #4
    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 <_oodTi96Tiboo_> Voir le message
    Soit le type "Type" qui extends "MyNumber<Type>"

    pourquoi n'est il pas possible de faire ce qui suit?
    Type a = new MyDouble();

    Or MyDouble est bien du type MyNumber<T>
    D'une part les normes de codages recommande d'utiliser une seule lettre en majuscule pour éviter les confusions. Bref tu devrais utiliser T à la place de Type.


    Ensuite non ce n'est pas la même chose, justement parce que le type exact des paramètres paramétrés n'est pas connu lors de la compilation de ta classe.

    Lorsque tu compiles ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class Triedre<T extends MyNumber<T>> {
    Tu sais que le type T étends MyNumber<T>, mais c'est tout. Tu ne peux pas en conclure autre chose ou lui attribuer un type fixe.

    En effet lorsque tu associes un objet de type "MyDouble" dans un objet de type T, tu casses la généricité.

    En effet cela marchera lorsque tu utiliseras un new Triedre<MyDouble>, mais que se passera-t-il lorsque tu instancieras un new Triedre<MyComplex> ?
    En effet T devrait correspondre alors à MyComplex, mais tu met un MyDouble dedans ce qui est impossible puisqu'il s'agit d'un type parent.
    C'est comme si tu écrivais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyComplex m = new MyDouble(0);



    Bref lorsque tu écris une classe générique, le type précis est inconnu et tu ne peux pas présumer qu'il s'agira d'un type précis. Sinon les generics sont inutiles...


    a++

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Bonjour AdiGuda,

    Merci pour ta réponse. Elle confirme mes dernières recherches sur les génériques.

    De ce fait, j'ai revu mon code hier soir. J'ai ajouté un constructeur à ma class abstract MyNumber prenant un "double" qui sera implémenté dans le class irritant de MyNumber:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public abstract class MyNumber<T> extends Number implements Numeric<T>{
     
    public MyNumber(){
    	this(0);
    }
     
    public MyNumber(double d) {}	// must be re-implemented by children
    ...
    Toutefois lors que je tente d'utiliser ce constructeur dans la class "Triedre", on me dit qu'il n'est pas possible d'instancier le type "Type".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class Triedre<Type extends MyNumber<Type>>{
    	private Type a;
    	private Type b;
    	private Type c;
    
    	public Triedre(double a, double b, double c) {
    		this.a = new Type(a);	// error : Cannot instantiate the type Type
    		this.b = new Type(b);	// error : Cannot instantiate the type Type
    		this.c = new Type(c);	// error : Cannot instantiate the type Type
    	}
    	...
    }
    Peux tu me dire pourquoi le construteur "MyNumber(double d)" n'est pas visible dans la class Triedre?

    PS: Merci pour le rappel des conventions de nommage des generics. Si j'ai utiliser <Type> au le de <T> c’était pour vérifier qu'il n'y avait pas de confusion entre les différents type generic.

  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
    Citation Envoyé par <_oodTi96Tiboo_> Voir le message
    J'ai ajouté un constructeur à ma class abstract MyNumber prenant un "double" qui sera implémenté dans le class irritant de MyNumber:
    Les constructeurs ne s'héritent pas, et ne peuvent donc pas être "implémenté" par des classes filles...


    Citation Envoyé par <_oodTi96Tiboo_> Voir le message
    Toutefois lors que je tente d'utiliser ce constructeur dans la class "Triedre", on me dit qu'il n'est pas possible d'instancier le type "Type".
    Normal : le type "Type" n'existe pas !!!


    En fait tu veux faire ceci :
    Mais c'est quoi T ?
    Cela peut être un MyDouble, un MyComplex... ou n'importe quelles autres classes héritant de MyNumber !
    Le compilateur ne peut pas décider de cela à ta place !


    Dis-toi bien qu'à l'intérieur du code d'une classe Generics, le type exact de T est inconnu. Donc le compilateur ne peut pas effectuer certaines opération comme new T() ou T.class...
    (enfin en vrai il pourrait le faire, mais cela aboutirait à du code non-typesafe, ce qui va à l'encontre même des Generics)



    Bref tu ne peux pas faire cela !
    Soit tu fait quelque chose de fortement typé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Triedre {
    	private MyDouble a;
    	private MyDouble b;
    	private MyDouble c;
     
    	public Triedre(double a, double b, double c) {
    		this.a = new MyDouble(a);
    		this.b = new MyDouble(b);
    		this.c = new MyDouble(c);
    	}
    }
    Soit tu fait quelque chose de complètement générique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Triedre<T extends MyNumber<T>>{
    	private T a;
    	private T b;
    	private T c;
     
    	public Triedre(T a, T b, T c) {
    		this.a = a;
    		this.b = b;
    		this.c = c;
    	}
    }
    Mais tu ne peux pas faire les deux.


    A la rigueur, tu peux te faire deux petite méthode factory pour simplifier la création de Triedre<MyDouble> ou Triedre<MyComplex> :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	public static Triedre<MyDouble> newDouble(double a, double b, double c) {
    		return new Triedre<MyDouble>(new MyDouble(a), new MyDouble(b), new MyDouble(c));
    	}
     
    	public static Triedre<MyComplex> newComplex(double a, double b, double c) {
    		return new Triedre<MyComplex>(new MyComplex(a), new MyComplex(b), new MyComplex(c));
    	}


    a++

    PS : Tant que tu n'encapsules pas les classes il n'y a aucun conflit dans les noms des paramètres Generics. C'est au contraire le fait d'utiliser un nom de classe qui apporte de la confusion dans la lecture du code...

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    j'aurai une petite nuance à ta réponse. Mais peut être que j'ai mal compris un truc.

    Je suis Ok sur le fait que "Type" n'est pas spécifiquement connu par la compilateur.

    Mais le compilateur sait qu'il extends MyNumber non?

    or si on déclare un constructeur dans MyNumber il doit pouvoir le voir non?

  8. #8
    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
    Citation Envoyé par <_oodTi96Tiboo_> Voir le message
    Mais le compilateur sait qu'il extends MyNumber non?
    Oui, et c'est tout ce qu'il sait.
    Du coup tu peux utiliser les méthodes définis dans MyNumber sur les objets de type T.

    Citation Envoyé par <_oodTi96Tiboo_> Voir le message
    or si on déclare un constructeur dans MyNumber il doit pouvoir le voir non?
    Non : les constructeurs ne n’héritent pas...


    a++

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    84
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Décembre 2006
    Messages : 84
    Points : 42
    Points
    42
    Par défaut
    Oui effectivement j’oublie toujours ce fait.

    Merci pour tes conseils. Je constate que tu est toujours aussi magnanime malgré les années. Bonne continuation.

    Sébastien.

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

Discussions similaires

  1. [JSP] Utilisation des Generics dans une scriptlet
    Par trochv dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 13/06/2006, 14h23
  2. [CR8.5] Utilisation des codes barre
    Par Robert dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 20/01/2005, 16h13
  3. utilisation des sockets sous windows
    Par Tupac dans le forum Réseau
    Réponses: 2
    Dernier message: 21/12/2002, 18h24
  4. [Crystal Report] Utilisation des vues de sql serveur
    Par Olivierakadev dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 15/11/2002, 17h44
  5. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01

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