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

Java Discussion :

Généricité en java


Sujet :

Java

  1. #1
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut Généricité en java
    Bonjour à tous,

    J'ai un problème en java que je n'arrive pas à résoudre.
    Je vous avertis d'entrée, je viens du "monde C++", et je suppose que si je n'arrive pas à faire ce que je veux en java, c'est que j'essaye de calquer des habitudes C++iennes

    Alors voilà, je fais actuellement parti d'un projet de recherche mettant au point un compilateur pour un langage dont les types sont composés.

    Un type effectif du langage est composé de l'intersection de 3 grandes classes de type :
    Type structurel - Vector4, Integer, Float, ...
    Type sémantique - Color, Normal, ...
    Type d'utilisation - Fragment ou Vertex

    J'ai donc le code 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
    // Interface pour les types sémantiques
    public interface SemanticType
    {
    }
     
    // Exemple de type sémantique
    public class Color implements SemanticType
    {
    }
     
    // Interface pour les types d'utilisation
    public interface UseType
    {
    }
     
    // Exemple de type d'utilisation
    public class Fragment implements UseType
    {
    }
     
    // Exemple de type d'utilisation
    public class Vertex implements UseType
    {
    }
     
    // Interface pour les types structurels
    public interface StructuralType
    {
    }
     
    // Exemple de type structurel
    public class Vector4 implements StructuralType
    {
    }
     
    // Type effectif
    public class Type <Semantic extends SemanticType, Use extends UseType, Structure extends StructuralType>
    {
      Semantic  semantic_;
      Use       use_;
      Structure structure_;
    }
    Je peux donc créer des variables avec des types effectifs de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Type<Color,Fragment,Vector4> color1;
    Type<Color,Vertex,Vector4>   color2;
    Pour le moment rien de bien incroyable.
    Le but maintenant est de gérer les casts entre ces types effectifs. Dans la mesure du possible, l'objectif serait d'avoir un système très souple, à savoir :
    - Ne pas avoir à maintenir à jour une liste de types existants, l'inférence doit se faire dynamiquement.
    - Ne pas disperser la logique de cast en plusieurs endroits, dans l'idéal une méthode par cast pour chaque types différents.

    C'est à dire qu'en C++, j'aurais voulu pouvoir faire quelque chose de ce genre :
    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
    void cast( Type<Color,Fragment,Vector4> color1, Type<Color,Vertex,Vector4> color2 )
    {
      // Gestion du cast
    }
     
    void cast( Type<Color,Vertex,Vector4> color1, Type<Color,Fragment,Vector4> color2 )
    {
      // Gestion du cast
    }
     
    void cast( Type<Color,Fragment,Vector3> color1, Type<Color,Vertex,Vector4> color2 )
    {
      // Gestion du cast
    }
     
    ...
    Cela semble être impossible en java.
    Erreur de 'name clash'.
    De ce que j'ai compris, java perd les informations sur les types génériques dès la compilation terminée (généricit par 'type erasure'). La signature de mes fonctions deviendrait donc :
    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
    void cast( Type color1, Type color2 )
    {
      // Gestion du cast
    }
     
    void cast( Type color1, Type color2 )
    {
      // Gestion du cast
    }
     
    void cast( Type color1, Type color2 )
    {
      // Gestion du cast
    }
     
    ...
    Ce qui bien sur n'est pas possible.


    Je voudrais donc savoir s'il y avait une solution propre, à ce problème, qui au final peut se résoudre à: faire du polymorphisme sur des types génériques.

    Le but étant évidemment d'éviter des constructions de la forme:
    - Je met des Object en argument
    - Une tonne de "instanceof" dans un gros switch
    - je dispatch sur la bonne méthode une fois les types trouvés

    Merci à tous ceux qui auront pris le temps de lire ce message

  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,


    Les types Generics ne sont pas castables sans que cela ne casse toutes leurs logiques. Je vais reprendre l'exemple des Lists qui me semble plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	List<Integer> listInteger = ...;
     
    	// Ceci est interdit malgré que Integer hérite de Number :
    	List<Number> listNumber = (List<Number>) listInteger;
     
    	// Car sinon en toute logique on pourrait faire ceci :
    	listNumber.add(new Double(0.0));
     
    	// => On vient d'ajouter un Double dans une liste d'Integer !

    Pourquoi as-tu besoin de ces casts ???

    a++

  3. #3
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Par défaut
    salut,

    Citation Envoyé par NewbiZ Voir le message
    Le but étant évidemment d'éviter des constructions de la forme:
    - Je met des Object en argument
    - Une tonne de "instanceof" dans un gros switch
    - je dispatch sur la bonne méthode une fois les types trouvés
    Et une sorte de factory de fonctions de cast, rangés par couples de types dans une HashMap plus ou moins accessible statiquement, dans laquelle les types vont s'enregistrer à leur construction ?

    C'est pas forcément idéal (notamment la notion de factory statique), mais c'est déjà moins horrible qu'un gros switch...

  4. #4
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Salut,
    Les types Generics ne sont pas castables sans que cela ne casse toutes leurs logiques.
    Pourquoi as-tu besoin de ces casts ???
    Hmm, je me suis mal fait comprendre
    Je ne veux pas caster des generics. Je veux implémenter les casts dans le langage en question qui n'est pas Java.
    Dans le compilateur, les types du langage sont représentés par une structure Type, qui elle, utilise la généricité.

    Et une sorte de factory de fonctions de cast, rangés par couples de types dans une HashMap plus ou moins accessible statiquement, dans laquelle les types vont s'enregistrer à leur construction ?

    C'est pas forcément idéal (notamment la notion de factory statique), mais c'est déjà moins horrible qu'un gros switch...
    C'est ce que j'ai commencé, à faire, mais c'est pas l'idéal :/

    Pour le moment ca donne quelque chose comme ca :
    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
     
    public interface Cast
    {
      public final Class<SemanticType>   FromSemantic  = SemanticType.class;
      public final Class<UseType>        FromUse       = UseType.class;
      public final Class<StructuralType> FromStructure = StructuralType.class;
     
      public final Class<SemanticType>   ToSemantic  = SemanticType.class;
      public final Class<UseType>        ToUse       = UseType.class;
      public final Class<StructuralType> ToStructure = StructuralType.class;
     
      public TypeB cast( TypeB v );
    }
     
    public class ColorVertexVector4_ColorFragmentVector4 implements Cast
    {
      public final Class<Color>   FromSemantic  = Color.class;
      public final Class<Vertex>  FromUse       = Vertex.class;
      public final Class<Vector4> FromStructure = Vector4.class;
     
      public final Class<Color>    ToSemantic  = Color.class;
      public final Class<Fragment> ToUse       = Fragment.class;
      public final Class<Vector4>  ToStructure = Vector4.class;
     
      public TypeB cast( TypeB v )
      {
        TypeB<Color, Vertex, Vector4> value = (TypeB<Color, Vertex, Vector4>)v;
        TypeB<Color, Fragment, Vector4> ret = TypeFactory.getInstance().create( Color.class, Fragment.class, Vector4.class );
     
        // ...
     
        return ret;
      }
    }
    Je créé plein de structures de ce genre héritant de l'interface Cast, et je les ranges dans une collection.
    Quand j'ai un cast à faire, je fais défiler la collection en analysant FromX et ToX jusqu'à trouver la bonne structure, et j'exécute sa méthode.

    Le problème c'est qu'il faut :
    1) Enregister les structures dans une collection, et ca ne peut se faire qu'à la main. Alors qu'avec de simples fonctions, c'est le polymorphisme qui recherche à notre place.
    2) Ca fait beaucoup de redondance je trouve, je dois répéter à de multiples endroits les mêmes informations de type ( dans l'exemple on le voit bien, les types de départ et d'arrivée sont écrits en au moins 3 exemplaires, si seulement il y avait ne serait-ce qu'un système de typedef )

  5. #5
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Ne serait-ce que pouvoir réduire le code plus haut à quelque chose dans ce genre, serait déjà bien suffisant :
    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
    // Interpolation de couleur
    public class ColorVertexVector4_ColorFragmentVector4 implements Cast
    {
      public final Class<TypeB> FromType = TypeB<Color,Vertex,Vector4>.class;
      public final Class<TypeB> ToType   = TypeB<Color,Fragment,Vector4>.class;
     
      public ToType cast( FromType v )
      {
        // ...
      }
    }
     
    // Suppression de l'alpha
    public class ColorVertexVector3_ColorVertexVector4
    {
      public final Class<TypeB> FromType = TypeB<Color,Vertex,Vector4>.class;
      public final Class<TypeB> ToType   = TypeB<Color,Vertex,Vector3>.class;
     
      public ToType cast( FromType v )
      {
        // ...
      }
    }
    Mais ce genre de choses n'a pas l'air possible.

  6. #6
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Par défaut
    Et avec un generic (template) pour ta classe cast ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class Cast<FromType, ToType> { /* ... */ }
    Le problème c'est qu'il faut : 1) Enregister les structures dans une collection, et ca ne peut se faire qu'à la main. Alors qu'avec de simples fonctions, c'est le polymorphisme qui recherche à notre place.
    Il me semble qu'en Java rien ne t'empêche de mettre un bout de code statique dans ta classe qui sera exécuté au chargement de celle-ci. Il pourra alors aller s'enregistrer tout seul dans la factory.

    Quand j'ai un cast à faire, je fais défiler la collection
    La HashMap sera plus efficace qu'une liste chaînée que tu parcours à chaque fois

  7. #7
    Membre chevronné
    Avatar de NewbiZ
    Profil pro
    Étudiant
    Inscrit en
    Juillet 2002
    Messages
    184
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2002
    Messages : 184
    Par défaut
    Citation Envoyé par nouknouk Voir le message
    Et avec un generic (template) pour ta classe cast ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class Cast<FromType, ToType> { /* ... */ }
    Ah oui donc avec ca par contre je suis obligé d'utiliser une hashmap je suppose ?
    Parceque si je n'ai pas fait comme ca, c'est parcequ'il semble impossible de récupérer les informations sur les types generiques une fois la classe instanciée (donc je les stoques dans des attributs Class<...>). Je vais implémenter tout ca avec des hashmap et on va voir ce que ca donne !
    Citation Envoyé par nouknouk Voir le message
    Il me semble qu'en Java rien ne t'empêche de mettre un bout de code statique dans ta classe qui sera exécuté au chargement de celle-ci. Il pourra alors aller s'enregistrer tout seul dans la factory.
    Superbe idée ! Je ne connaissais pas ce fonctionnement, c'est très sympa.
    Citation Envoyé par nouknouk Voir le message
    La HashMap sera plus efficace qu'une liste chaînée que tu parcours à chaque fois
    Hmm je vais voir ca, mais du coup ca me rajoute de la redondance, stocker les types sous forme de chaine + sous forme de classe. Mais effectivement ca speedera surement le tout

    Merci encore pour ces réponses, je vais tenter d'implémenter tout ca.

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

Discussions similaires

  1. La généricité en Java et le mot clé super
    Par win_ubuntu dans le forum Général Java
    Réponses: 10
    Dernier message: 14/05/2015, 10h08
  2. L'utilité de la généricité de Java
    Par spring.time dans le forum Général Java
    Réponses: 10
    Dernier message: 02/02/2014, 22h16
  3. Généricité développement Java
    Par debloc dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 12/12/2012, 11h01
  4. Comment utiliser la généricité en java ?
    Par Adorien dans le forum Langage
    Réponses: 3
    Dernier message: 27/04/2010, 12h35
  5. Généricité en Java (classe avec paramètre)
    Par epcilone059 dans le forum Langage
    Réponses: 1
    Dernier message: 27/03/2009, 12h05

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