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 :

[generics] pb d'implémentation d'une itf


Sujet :

Langage Java

  1. #1
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut [generics] pb d'implémentation d'une itf
    Bonjour à tous,

    J'ai une interface dans laquelle je déclare certains paramètres de méthodes basés sur les generics :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public interface Visitor<N extends InstanceNoeudItf> {
    	void visit(N noeud);
    }
     
     
    public interface InstanceNoeudItf {
    	void accept(Visitor<? extends InstanceNoeudItf> visitor);
    ...
    }
    Qui convient aux classes clients avec toutes les classes implémentant InstanceNoeudItf ou l'interface InstanceNoeudItf elle-même. C'est l'objectif.

    Mais impossible de compiler mon implémentation (The method visit(capture#1-of ? extends InstanceNoeudItf) in the type Visitor<capture#1-of ? extends InstanceNoeudItf> is not applicable for the arguments (InstanceNoeud)) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class InstanceNoeud extends BasicInstanceNoeud implements InstanceNoeudItf {
    ...
    	public void accept(Visitor<? extends InstanceNoeudItf> visitor) {
    		visitor.visit(this);
    	}
    ...
    }
    J'ai essayé de déclarer mon implémentation de #accept de différentes façons, sans succès (violation de la signature de l'interface héritée) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public void accept(Visitor<InstanceNoeudItf> visitor) {
    ...
    public void accept(Visitor<InstanceNoeud> visitor) {
    ...

    Du coup, j'ai déclaré ceci, qui compile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public interface InstanceNoeudItf {
    	void accept(Visitor<InstanceNoeudItf> visitor);
    ...
    }
     
    public class InstanceNoeud extends BasicInstanceNoeud implements InstanceNoeudItf {
    	public void accept(Visitor<InstanceNoeudItf> visitor) {
    		visitor.visit(this);
    	}
    ...
    }
    Mais qui est refusé par les classes clientes :
    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 CalculAffichageVisitor implements Visitor<InstanceNoeud> {
    ...
    	public void visit(InstanceNoeud noeud) {
    	...
    	}
    ...
    	public static void initialiser(InstanceNoeud racine) {
    		CalculAffichageVisitor visitor = new CalculAffichageVisitor();
    		racine.accept(visitor);
    	}
    ...
    }
    Je tourne en rond ! C'est comme si InstanceNoeud n'implémentait pas InstanceNoeudItf.
    Est-ce que quelqu'un comprend ce que je fais de travers, SVP ?
    Merci d'avance.

  2. #2
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    Truc curieux, Eclipse indique bien une surcharge de la méthode concrète #visit (petit triangle à gauche de la déclaration), mais la compilation échoue si je mets une annotation @override au-dessus :

    Multiple markers at this line
    - implements com.xxx.arbre.eval.Visitor<com.xxx.business.InstanceNoeud>.visit
    - The method visit(InstanceNoeud) of type CalculAffichageVisitor must override a superclass method

  3. #3
    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 tooms4444 Voir le message
    Truc curieux, Eclipse indique bien une surcharge de la méthode concrète #visit (petit triangle à gauche de la déclaration), mais la compilation échoue si je mets une annotation @override au-dessus :
    Si tu compiles en source-level 1.5 c'est normal.
    Sous Java 1.5 l'annotation @Override s'applique uniquement aux méthodes qui redéfinissent une méthodes existante et concrète. Ce n'est que sous Java 6 qu'elle a été modifié afin de s'appliquer également aux méthodes abstraites...





    Pour ton problème, c'est un peu un casse-tête : tu veux à la fois quelque chose de super-generics, et de l'autre quelque chose de très typé...

    Du coup il te faut une référence croisé pour "conserver" les types :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    interface Visitor<N extends InstanceNoeudItf<N>> {
    	void visit(N noeud);
    }
     
    interface InstanceNoeudItf<T extends InstanceNoeudItf<T>> {
    	void accept(Visitor<T> visitor);
    }
    Qu'il faut préciser dans ton noeud :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class InstanceNoeud implements InstanceNoeudItf<InstanceNoeud> {
    	public void accept(Visitor<InstanceNoeud> visitor) {
    		visitor.visit(this);
    	}
    }

    Mais bon c'est un peu lourd à lire


    a++

  4. #4
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    OK, ça me semble clair ; et en plus ça compile

    En fait, je souhaite créer un adaptateur d'InstanceNoeud. C'est pourquoi j'en ai extrait une interface réduite que je souhaite ensuite appliquer à un mock.
    Mais tout se complique avec le visiteur...

    Nouvelle question : comment puis-je écrire des visiteurs basés sur l'itf ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public class ExtractionTotaleVisitor implements Visitor<InstanceNoeudItf<InstanceNoeudItf> {
    ...
    }
    => refusé à la compilation ; qq chose doit encore m'échapper

    Multiple markers at this line
    - Bound mismatch: The type InstanceNoeudItf<InstanceNoeudItf> is not a valid substitute for the bounded parameter <N extends InstanceNoeudItf<N>> of the type
    Visitor<N>
    - InstanceNoeudItf is a raw type. References to generic type InstanceNoeudItf<T> should be parameterized
    - Bound mismatch: The type InstanceNoeudItf is not a valid substitute for the bounded parameter <N extends InstanceNoeudItf<N>> of the type Visitor<N>
    - Bound mismatch: The type InstanceNoeudItf is not a valid substitute for the bounded parameter <T extends InstanceNoeudItf<T>> of the type InstanceNoeudItf<T>
    - InstanceNoeudItf is a raw type. References to generic type InstanceNoeudItf<T> should be parameterized
    Pourrais-tu donner un exemple d'implémentation du visiteur, STP ?

  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
    Tu ne peux pas avoir quelques choses de très fortement typés qui soient en même temps légèrement typés en offrant plus de libertés...


    Que veux-tu faire précisément ?

    a++

  6. #6
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut
    Ce que je veux...

    J'ai une classe, InstanceNoeud, qui est très technique. Or nous devons lui substituer une autre représentation mémoire parce qu'il y aura dorénavant deux sources distinctes. J'ai donc créé une interface minimale pour implémenter un adaptateur.

    Mais slt voilà, le champ d'utilisation d'InstanceNoeud est tellement vaste (des tas de visiteurs qui font des traitements différents) que je souhaite conserver parfois le type InstanceNoeud pour les paramètres et types de retour. Dans ce cas, seule la structure originelle serait traitable ; dans les autres cas, tous les adaptés doivent être acceptés.
    D'où l'idée des generics.

    Sans doute que je me fourvoie et que le type devrait être partout l'itf, mais je n'y vois pas très clair pour le moment...

  7. #7
    Membre habitué
    Homme Profil pro
    Architecte senior Java EE/Spring - ScrumMaster
    Inscrit en
    Juin 2010
    Messages
    229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France

    Informations professionnelles :
    Activité : Architecte senior Java EE/Spring - ScrumMaster
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2010
    Messages : 229
    Points : 162
    Points
    162
    Par défaut ah ah, j'crois que j'tiens un truc, là
    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 class ExtractionVariablesVisitor<T extends InstanceNoeudItf<T>> implements Visitor<T> {
    	public void visit(T noeud) {
    	...
    	}
    }
     
     
    public static <T extends InstanceNoeudItf<T>> String getExpandedName(T noeud) {
    	// extrait les variables du sous arbre
    	ExtractionVariablesVisitor<T> extracteur = new ExtractionVariablesVisitor<T>();
    	noeud.accept(extracteur);
    ...
    }
    En même temps, tu m'avais bien dit que ça serait dur à relire !

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 04/04/2006, 23h22
  2. Implémentation d'une jointure "rien=tout"
    Par lafeuil dans le forum Langage SQL
    Réponses: 3
    Dernier message: 15/03/2006, 16h26
  3. Implémentation d'une liste chaînée
    Par Yux dans le forum C
    Réponses: 22
    Dernier message: 02/03/2006, 20h31
  4. Réponses: 5
    Dernier message: 23/02/2006, 00h34
  5. Réponses: 12
    Dernier message: 01/07/2004, 11h03

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