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 :

Interfaces + Héritage + Polymorphisme + Surcharge = Soucy


Sujet :

Langage Java

  1. #1
    Membre du Club
    Inscrit en
    Mai 2004
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 40
    Points : 49
    Points
    49
    Par défaut Interfaces + Héritage + Polymorphisme + Surcharge = Soucy
    Bonjour,

    Dans le cadre d'un TD de Java, j'aurais voulu coder un truc joli mais au final ça marche pas exactement comme je voudrais. Exemple de définition des classes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class A {}
    class B extends A {}
    class C extends A {}
    class D extends A {}
    Avec une interface :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    interface exemple {
        void methode(A param)
    }
    Et un code final :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Prog implements exemple  {
        void methode(B param);
        void methode(C param);
        void methode(A param);
    }
    Je sous obligé d'utiliser les interfaces pour gérer des événements (c'est dans le sujet), et je souhaiterais que lorsque j'appelle la méthode "methode" de la classe Prog, il exécute celle qui va bien : la première si param est de type B, la seconde si param est de type C, et la dernière dans tous les autres cas (pour respecter l'interface).

    Seulement, dans tous les cas, il utilise la troisième classe, peu importe que param soit de type A, B ou C. Je bloque.

    Avez-vous une solution ? Ce genre de problèmes est-il surmontable ?

    Merci.
    Où va le monde ? Vers le futur ? Vers le passé ?
    Sans réponse ?

  2. #2
    Expert éminent
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Points : 7 679
    Points
    7 679
    Par défaut
    Bonjour,
    Tu y vas avec la surcharge alors que la redéfinition est bien meilleure.
    Le but de la redéfinition et le polymorhisme est justement de ne pas avoir à gérer au cas par cas, plutôt utiliser une classe indépendanmment de son type.

    Bref, si tu définis une interface IBase par exemple et que A, B et C l'implémenentent, tu pourras te contenter de:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    class Prog  {
        void methode(IBase param);
    }
    en invoquant la/les méthodes définies dans IBase depuis Prog.methode, tu auras le comportement attendu, i.e. selon le type d'instanciation.

  3. #3
    Membre du Club
    Inscrit en
    Mai 2004
    Messages
    40
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 40
    Points : 49
    Points
    49
    Par défaut
    Merci pour la réponse.

    C'est ce que j'aurais fait si je ne voulais pas différencier le comportement suivant que le paramètre passé soit de type B, de type C, ou d'un autre type dont je me fiche a priori tant que ce type hérite de A (en utilisant donc le polymorphisme pour ce dernier cas).
    La solution "moche" qui me viendrait à l'esprit serait de différencier dans une méthode générale acceptant n'importe quel objet de type A, et en regardant avec un getName(), mais il doit y avoir mieux.

    Ou alors j'ai pas compris comment différencier...
    Où va le monde ? Vers le futur ? Vers le passé ?
    Sans réponse ?

  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,


    C'est normal que cela ne marche pas puisque lors d'une surcharge c'est le type déclaré de la référence qui est utilisé à la compilation pour déterminer la méthode a appelée.


    Bref il te faut rediriger manuellement vers la bonne méthode, mais plutôt que d'utiliser getName() il serait plus propre d'utiliser instanceof :
    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
    	void methode(B param) {
     
    	}
        void methode(C param) {
     
        }
        void methode(A param) {
        	if (param instanceof B) {
        		methode((B)param);
        	} else if (param instanceof C) {
        		methode((C)param);
        	} else {
        		// code par défaut
        	}
        }
    a++

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Points : 540
    Points
    540
    Par défaut
    Je rebondis sur ce post car je rencontre fréquemment ce genre de cas et je voulais savoir si ce serait traité dans les futures versions de java :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    interface ITest {
        public void valider(A a);
    }
     
    abstract class A {}
    class B extends A implements ITest {
        public void valider(B b) {}
    }
    Bah ça compile pas, hors je ne vois pas ce qui pourrait poser problème, même au compilateur, qui ferait que cette syntaxe serait interdite...

    Je vais avoir besoin de tes lumières maître adiGuba

  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
    C'est normal que cela ne fonctionne pas et cela ne fonctionnera jamais : tu casses les règles de la POO

    En implémentant l'interface ITest tu dois respecter son contrat, ce qui n'est pas le cas ici puisque la méthode valider(A) a disparu (tu ne peux pas passer un objet de type A à la méthode valider(B)).

    En modifiant le type d'un des paramètres d'une méthode, tu sors du cadre de la redéfinition/implémentation : ce n'est plus la même méthode (lire la FAQ : Quelles sont les règles à respecter pour redéfinir/implémenter une méthode ?).


    En effet comme tu implémentes ITest tu peut donc faire ceci :
    puis avec une éventuelle classe C étendant A tu dois pouvoir faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test.valider(new C()); // appelle valider(A)
    Or tu n'as pas implémenté la méthode valider(A) !




    Si tu veux une méthode dont le type des paramètres varient, il faut utiliser les Generics :
    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
    /**
     * @param <T> Le type utilisé pour le paramétrage de l'interface (A ou une classe fille)
     */
    interface ITest<T extends A> {
        public void valider(T t);
    }
     
     
    /**
     * On implémente ITest en conservant le même paramétrage :
     */
    class A1<T extends A> extends A implements ITest<T> {
        public void valider(T t) {}
    }
     
    /**
     * On implémente ITest en spécilisant le paramétrage
     * (les classes filles devront également utilisé B)
     */
    class A2 extends A implements ITest<A2> {
        public void valider(A2 b) {}
    }
     
    /**
     * On implémente ITest en spécialisant le paramétrage sur une classe fille :
     */
    class A3<T extends A2> extends A implements ITest<T> {
        public void valider(T t) {}
    }

    a++

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    442
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 442
    Points : 540
    Points
    540
    Par défaut
    Effectivement je suis un peu concon, genre si tu mets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    interface ITest {
        public void valider(Object o);
    }
    Et que derrière tu essais de valider un String... et que tu as injecté autre chose que String...

    J'avais pas pensé aux Generics, c'est une bonne idée, merci !

Discussions similaires

  1. héritage et surcharge
    Par babar63 dans le forum C++
    Réponses: 7
    Dernier message: 17/01/2007, 23h23
  2. [Héritage] [Polymorphisme] Question de débutant ?
    Par TSnarfK dans le forum Langage
    Réponses: 9
    Dernier message: 12/09/2006, 15h39
  3. [G++] Héritage et surcharge de fonction
    Par Beuss dans le forum Autres éditeurs
    Réponses: 11
    Dernier message: 15/05/2006, 09h18
  4. Réponses: 2
    Dernier message: 25/07/2004, 23h24

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