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 :

Polymorphisme en JAVA


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2017
    Messages : 3
    Par défaut Polymorphisme en JAVA
    Bonjour à tous,

    J'ai un peu de mal à comprendre le polymorphisme dans JAVA... Comment il fonctionne et comment JAVA le comprends et le compile puis l’exécute.

    Voici mon code:

    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
    43
    44
    45
    46
    47
    48
     
    public class A {
     
    	public String f(D obj) {
    		return "AD";
    	}
     
    	public String f(A obj) {
    		return "AA";
    	}
    }
     
    public class B extends A {
    	public String f(B obj) {
    		return "BB";
    	}
     
    	public String f(A obj) {
    		return "BA";
    	}
    }
     
    public class C extends B {
     
    }
     
    public class D extends B{
     
    }
     
    public class tr {
    	public static void main(String[] args) {
    	A a1= new A();
    	A a2=new B();
    	B b= new B();
    	C c= new C();
    	D d= new D();
    	System.out.println(a1.f(b));
    	System.out.println(a1.f(c));
    	System.out.println(a1.f(d));
    	System.out.println(a2.f(b));
    	System.out.println(a2.f(c));
    	System.out.println(a2.f(d));
    	System.out.println(b.f(b));
    	System.out.println(b.f(c));
    	System.out.println(b.f(d));
    	}
    }
    J'obtiens l'affichage suivant:
    AA // ici je comprends
    AA // idem
    AD // idem
    BA // je ne comprends pas l'affichage ici, si je suis le principe de la résolution dynamique comment je le comprends, j'obtiens BB.. Vu que a2 a comme type effectif: B. Donc pour moi on a un truc du genre "Object B.f(Object B)".. Je ne comprends vraiment pas la technique...
    BA // ici je ne comprends pas non plus
    AD // ici non plus
    BB
    BB
    AD


    Si quelqu'un peut m'expliquer sa technique je suis preneur...

    Merci d'avance,
    Cordialement,
    Tootun

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Hello,

    peut-être que ça aiderait de bien faire la différence entre ce qui se passe au moment de la compilation, et ce qui se passe au moment de l'exécution.

    Comme son nom l'indique, ce qui est dynamique, c'est à l'exécution. Là, on est en train de manipuler des vrais objets en live, et l'implémentation de leurs comportement peut dépendre de quelle est leur classe réelle maintenant qu'on est bel et bien en train de les exécuter et qu'on les a sous la main pour connaître leur classe.

    Par contre, tout ce qui se passe à la compilation, pendant qu'on est en train d'écrire le programme, ça c'est entièrement statique. Pendant la compilation, le programmeur sait peut-être, parce qu'il le déduit en lisant le programme, quelles seront les classes réelles des objets manipulés. Mais le compilateur, lui, n'en sait rien. Il n'a pas les objets disponibles pour vérifier leur type comme ce sera le cas à l'exécution.

    Or, il faut bien comprendre que choisir quels champs on va lire/écrire, choisir quelle méthode on appelle, tout cela, c'est fait à la compilation. C'est statique.
    Ce qui est dynamique, et qui peut dépendre des types réels, c'est quelle est l'implémentation réelle que fournit l'objet pour la méthode qu'on a décidé d'appeler. Certes les méthodes ont déjà été décidées à la compilation... Mais les sous-classes peuvent décider de redéfinir leurs méthodes : ce sont toujours les mêmes qu'on a décidé d'appeler, mais leur comportement est différent.

    Tu dis que pour a2.f(b) => BA, tu ne comprends pas. Tu te dis que l'objet B sur lequel on appelle une méthode f(), ça devrait être sa méthode f(B), puisque le paramètre b est de type B.
    Oui mais, quelle méthode est appelée, c'est décidé à la compilation. C'est à dire à un moment où on ne connaît pas les types réels des objets. Or l'objet a2 semble peut-être évidemment de type B, mais ça, ça ne sera connu qu'à l'exécution. À la compilation, il est déclaré comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A a2 = quelque chose qui sera évalué à l'exécution;
    Imagine que B ne définisse pas de méthode f(B) mais à la place une méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public String toto() {
      return "toto";
    }
    Tu crois vraiment que tu pourrais appeler a2.toto() ?

    Eh ben non, puisque a2 est une variable de type A, et que la classe A n'a pas de méthode toto() que tu pourrais possiblement appeler.

    C'est pareil. La classe A n'a pas non plus de méthode f(B). Elle a une méthode f(A) et une méthode f(D), donc c'est l'une des deux qui peut être appelée. Elle n'a pas de méthode f(B), et donc cette méthode qui n'existe pas ne sera pas appelée.
    Celle qui est choisie n'est pas f(D) car le paramètre, b, est de type B qui n'est pas un sous-type de D.
    Par contre, le type B est un sous-type de A, donc rien ne s'oppose à choisir la méthode f(A), ce qui est donc fait.
    La compilation est faite, c'est décidé, c'est la méthode f(A) qui est appelée avec ce code.

    Ensuite, à l'exécution, il se trouve que l'objet contenu dans la variable a2, est un objet de classe B. Et la classe B redéfinit la méthode f(A), celle qu'on a choisi d'appeler. C'est donc la méthode f(A) de la classe B qui est exécutée.

    Même raisonnement pour les autres : la méthode qui sera appelée, ça se choisit à la compilation. L'implémentation de cette méthode par les objets sur lesquelles on l'appelle, ça dépend de quelle implémentation ces objets fournissent à l'exécution, du fait de leur classe réelle.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Il faut savoir que le compilateur, il va utiliser les signatures des méthodes, pas seulement leur nom. Il va parcourir toutes les méthode et construire un appel qu'il stockera dans la jvm. Ensuite, à l'exécution, la JVM va appeler la méthode ayant cette signature, mais sur l'instance réelle. Décomposons ton code comme le vois le compilateur. Je vais utiliser une notation sans parenthèse pour bien distinguer le code de la classe compilée

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Classe A
       méthode f__D
       méthode f__A
    Classe B (extends A)
       méthode f__B
       méthode f__A
    Ton code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	A a2;
    	C c;
            a2.f(c));
    le compilateur analyse a2 et c.
    a2 est de type A.
    Il doit donc trouver une méthode f dans A. Au choix: f__D f__A
    c est de type C. Il n'y a pas de méthode f__C. Par contre il ya bien une f__A qui est compatible.

    Le code compilé deviens donc

    a2.f__A(c)

    A l'exécution maintenant. La jvm a une instance a2 qui contient un B. Elle va donc chercher f__A dans B qu'elle trouve et va l'appeler.


    Deuxième cas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	A a2;
    	D d;
            a2.f(d));
    le compilateur analyse a2 et d.
    a2 est de type A.
    Il doit donc trouver une méthode f dans A. Au choix: f__D f__A
    d est de type D. Il y a bien une f__D qui est compatible.

    Le code compilé deviens donc

    a2.f__D(d)

    A l'exécution maintenant. La jvm a une instance a2 qui contient un B. Elle va donc chercher f__D dans B qu'elle ne trouve pas. Elle va alors inspecter le parent A, va trouver ce f__D et l'appeler.

Discussions similaires

  1. Le polymorphisme en Java
    Par anaaa dans le forum Langage
    Réponses: 14
    Dernier message: 03/02/2012, 15h35
  2. polymorphisme en java
    Par l'unique dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 20/12/2010, 18h20
  3. Réponses: 7
    Dernier message: 18/06/2008, 19h01
  4. Polymorphisme en java ?
    Par cannavaro2006 dans le forum Langage
    Réponses: 3
    Dernier message: 31/01/2007, 13h17
  5. débutant java Polymorphisme
    Par Bba_M dans le forum Langage
    Réponses: 8
    Dernier message: 12/06/2006, 09h39

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