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 :

Interface générique : désigner la classe implémentant


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mai 2008
    Messages : 37
    Par défaut Interface générique : désigner la classe implémentant
    Salut,

    Je cherche le moyen de désigner la classe implémentant mon interface générique pour pouvoir l'utiliser dans mes signatures de méthodes. Par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    package test;
     
    public interface MonInterface<classe_implémentant>
    {
        public classe_implémentant getMonContenu();
     
        public void setMonContenu(classe_implémentant);
    }
    Une idée ?

  2. #2
    Membre émérite
    Avatar de michel.di
    Homme Profil pro
    Freelance
    Inscrit en
    Juin 2009
    Messages
    782
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 782
    Par défaut
    Salut,
    Remplace classe_implementant par T
    Regarde du côté des Generics!

  3. #3
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Bonjour,

    je ne suis pas sûr d'avoir compris ton besoin. Une implémentation de ton interface devrait ressembler à ça: ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class MonImplementation implements MonInterface<MonImplementation>
    {
        public MonImplementation getMonContenu() {
            ???
        }
        public void setMonContenu(MonImplementation param) {
            ???
        }
    }
    Quel intérêt cela pourrait avoir pour une implémentation d'avoir en champ une instance d'elle-même?

  4. #4
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    public interface MonInterface<T extends MonInterface<T>>
    {
        public T getMonContenu();
     
        public void setMonContenu(T t);
    }

  5. #5
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mai 2008
    Messages : 37
    Par défaut
    Merci pour vos réponses.

    Peu importe la raison, il est juste nécessaire qu'une classe implémentant mon interface ait une référence sur un objet de la même classe.

    Le problème en indiquant T comme paramètre est que je peux avoir n'importe quel type. Voici plus exacement ce que je souhaiterai avoir :

    Interface

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    package test;
     
    public interface MonInterface<T super classe_implémentant>
    {
        public T getMonContenu();
     
        public void setMonContenu(T t);
    }
    Implémentation

    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 MonImplementation extends UneSuperClasseQuelconque  implements MonInterface<UneSuperClasseQuelconque>
    {
        public UneSuperClasseQuelcoonque getMonContenu()
        {
            //TODO
        }
     
        public void setMonContenu(UneSuperClasseQuelconque uscq)
        {
            //TODO
        }
    }
    Si je voulais être statique avec le générique MonInterface, je pourrais mettre MonInterface à la place de classe_implémentant. Sauf que le problème est que je veux être dynamique sur ce point.

    J'espère avoir été plus clair cette fois.

  6. #6
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    La réponse que j'ai donnée ne convient pas ? C'est précisément ce qu'il faut écrire pour induire une dépendance du paramètre générique sur l'interface ou la classe générique elle-même.

  7. #7
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mai 2008
    Messages : 37
    Par défaut
    Citation Envoyé par herve91 Voir le message
    La réponse que j'ai donnée ne convient pas ? C'est précisément ce qu'il faut écrire pour induire une dépendance du paramètre générique sur l'interface ou la classe générique elle-même.
    Désolé j'ai rédigé ma réponse pendant que tu as posté la tienne.

    Ta solution me permettra d'avoir n'importe quel contenu tant que celui-ci implémente l'interface MonInterface. Or je veux que le contenu soit du type de la classe implémentant (ou un super type, cf mon deuxième exemple de code).

    En fait j'espérais qu'il-y-ait un mot clef ou une astuce quelconque permettant de désigner la classe implémentant.

  8. #8
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    À ma connaissance il n'y à pas moyen de distinguer interface ou classe. Par contre je ne vois pas l'intérêt de préciser une classe d'implémentation plutôt que l'interface... C'est vouloir imposer une contrainte là où il n'y en a pas. Il est toujours préférable de désigner une interface plutôt qu'une classe concrète.

  9. #9
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    Citation Envoyé par le2tbomi Voir le message
    Peu importe la raison
    Je ne suis pas tout à fait d'accord, ma question n'était pas anodine.

    En mettant des Generics un peu partout, on peut se retrouver piégé.
    Je ne dis pas que c'est le cas de ton problème, mais il y a des cas où à force de mettre des Generics, on finit par caster avec des classes génériques, ce qui ne veut pas dire grand chose, vu que le cast est fait à l'exécution...

    Il ne faut pas perdre à l'esprit que les Generics servent à éviter des erreurs de compilation.

    C'est pourquoi je voulais en savoir plus sur les raisons des contraintes que tu as exprimé. Il se peut qu'en creusant un peu, on puisse trouver une solution dans une autre direction mais qui te conviennes aussi bien.

    PS: et y'a aussi le fait que je suis curieux de nature

  10. #10
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mai 2008
    Messages : 37
    Par défaut
    Ok pour vos remarques. Voici donc la problématique en détail.

    Je cherche à construire une interface représentant un nœud. L'interface s'appellerait donc Node (plus haut désignée par MonInterface). Cette interface décrit les méthodes permettant d'ajouter des sous nœud ainsi que des feuilles.

    L'exemple le plus concret que je puisse trouver est un système de fichier : le nœud dossier contient des sous dossiers et des fichiers. De plus, si on exclue les représentations logiques, il n'est pas question qu'un dossier ne contienne autre chose que des sous-nœuds dossier et des feuilles fichier.

    J'en ai déduit l'interface suivante pour mon Node :

    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
     
    public interface Node<T super classe_implementant, Content>
    {
        //Ci dessous les méthodes gérant la collection de sous-nœuds
        public void addNode(T node);
     
        public void removeNode(T node);
     
        public Collection<T> getNodes();
     
        public void setNodes(Collection<T> nodes);
     
        //Ci dessous les méthodes gérant la collection de feuilles
        public void addContent(Content content);
     
        public void removeContent(Content content);
     
        public Collection<Content> getContents();
     
        public void setContents(Collection<Content> content);
    }
    Pour en revenir à mon exemple, étant donné qu'il n'est pas question que mon dossier comporte autre chose que des sous-nœuds dossier, je dois restreindre l'utilisation des méthodes add, remove get et set des sous-nœuds avec la classe implémentant (ou au pire l'un de ses super types).

    Voila pourquoi je souhaiterai avoir une signature telle que celle-ci pour mon interface.

    En fins connaisseurs, vous remarquerez que cette interface fait largement penser au design pattern Composite, en restreignant son utilisation.

    La solution la plus simple serait de déclarer une classe implémentant de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public class MaClasse implements Node<MaClasse, String>
    {
        //TODO
    }
    Sauf que cette déclaration ne me convient pas car il revient à la responsabilité du développeur utilisant l'interface que le contrat de l'utilisation de l'interface Node soit respecté. Ceci va à l'encontre de l'utilisation d'interface qui permet de déléguer cette responsabilité au compilateur (en quelque sorte).

    Merci pour l'intérêt que vous montrez à mon problème.

  11. #11
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    C'est étrange, je me suis plongé dans un problème très proche il y a moins d'un mois...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public interface Node<T super classe_implementant, Content>
    ce 'super' me gène, il laisserai mettre des objets qui ne sont pas des Nodes (Object par exemple).

    Après, il semble que tu souhaites imposer des contraintes fortes à celui qui réalise l'implémentation de ton interface.
    Sauf erreur de ma part, tu ne pourras pas faire mieux que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public interface Node<T extends Node, Content>
    Cela laissera évidemment la possibilité de déclarer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class MaClasse implements Node<Node, String>
    et d'ajouter des nodes de type différent.

    Ceci dit, s'il fait cela, il perdra la connaissance que ses Fils seront des 'MaClasse' et sera obligé de les caster en 'MaClasse' (ou autre)...

  12. #12
    Membre averti
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2008
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Mai 2008
    Messages : 37
    Par défaut
    Effectivement, plus j'y réfléchis, et plus je pense que ce super n'est pas du meilleur goût. Il serait sans doute préférable d'utiliser un extends.

    La solution que tu me propose est effectivement réalisable mais nous sommes d'accord pour dire qu'il ne s'agit pas d'une solution "secure".

    Cela étant, si il n'y a que cette solution ...

    J'aimerais néanmoins avoir plus d'avis, bien que ceux que j'ai eu sont tout à fait pertinents.

  13. #13
    Membre Expert Avatar de herve91
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    1 282
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 282
    Par défaut
    Je n'arrive toujours pas à comprendre pourquoi le code suivant ne conviendrait pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public interface Node<Content, T extends Node<Content, T>> {
        public void addNode(T node);
    }
     
    public class Dossier implements Node<String, Dossier> {
       public void addNode(Dossier dossier) {
       ...
       }
    }
    Tu ne peux pas ajouter à un Dossier autre chose que des Dossiers...

  14. #14
    Membre émérite
    Inscrit en
    Mars 2006
    Messages
    848
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 848
    Par défaut
    En fait, si j'ai bien compris, il aimerait contraindre celui qui écrit l'implémentation à écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class Dossier implements Node<String, Dossier> {
    plutôt que ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class Dossier implements Node<String, AutreClasse> {
    qui lui donnerait la possibilité d'avoir des fils qui ne sont pas du même type que le père.

    Après, à part en écrivant lui-même l'implémentation, je ne vois pas comment c'est possible.

Discussions similaires

  1. C# => VB.net classe, interface générique
    Par Gr@nd@x dans le forum VB.NET
    Réponses: 2
    Dernier message: 27/10/2008, 13h27
  2. Réponses: 3
    Dernier message: 08/07/2008, 15h31
  3. Réponses: 4
    Dernier message: 08/02/2008, 13h01
  4. Réponses: 5
    Dernier message: 26/07/2006, 17h01
  5. Réponses: 5
    Dernier message: 23/02/2006, 00h34

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