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 :

UpCasting non respecté avec une méthode surchargée


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut UpCasting non respecté avec une méthode surchargée
    Soit une classe A :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class A {
     
        public void afficher () {
            System.out.println ("A");
        }
     
    }
    et une classe fille B qui surcharge la méthode afficher :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class B extends A {
     
        // surcharge
        public void afficher () {
            System.out.println ("B");
        }
    }
    L'exécution du code suivant montre que le cast de B vers A (upcasting) est ignoré !?

    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
    public class TestUpcasting {
       
        public static void main(String[] args) {
            
            A objetA = new A();
            objetA.afficher ();
            // => affiche 'A' (pas de surprise)
            
            B objetB = new B();
            objetB.afficher ();
            // => affiche 'B' (pas de surprise là non plus)
            
            ((A) objetB).afficher ();
            // => affiche 'B' au lieu de 'A' !?
    
        }
    
    }
    1/ Pourquoi la méthode B.afficher() est-elle appelée au lieu de la méthode A.afficher() ?

    2/ Comment transformer un objet B en objet A ?

  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,

    Citation Envoyé par Nicolas Dansel Voir le message
    1/ Pourquoi la méthode B.afficher() est-elle appelée au lieu de la méthode A.afficher() ?
    Le compilateur génère bien dans le code un appel à la méthode A.afficher(), mais à l'exécution le type réel de l'objet est vérifié pour déterminer la méthode à appeler : B.afficher() dans ce cas.

    Si tu viens du C++ dis-toi qu'en Java toutes les méthodes sont virtuelle par défaut.

    Citation Envoyé par Nicolas Dansel Voir le message
    2/ Comment transformer un objet B en objet A ?
    Humm... C'est à dire ?

    a++

  3. #3
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut
    Merci pour votre réponse rapide.

    Q1/ Il y a donc un écart entre le code tel qu'on le lit dans l'éditeur et le code réellement exécuté. Je m'en doutais :-) Maintenant, j'en suis sûr.

    Q2/ Disons que j'ai créé un objetB par erreur et que je veux maintenant le déclasser en pur objetA. Comment faire ?

    Le code suivant montre une tentative non concluante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            A objetAbis = new A();
            objetAbis = objetB;
            objetAbis.afficher();
            // => affiche encore 'B' au lieu de 'A' ?!

  4. #4
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut Remarque sur une doc Java
    Page suivante :

    http://fr.wikibooks.org/wiki/Program.../Polymorphisme

    Seconde section : Polymorphisme d'héritage (par redéfinition de méthodes dans une sous-classe)

    La dernière remarque me semble fausse au vu de ce que nous savons maintenant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public static void main(String[] args) {
      B ob1= new B(10,20);
      ((A)ob1).getter(); // Par type casting, appel de methode getter de la classe A
     }
    La méthode qui va s'exécuter sera en fait B.getter !

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    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 483
    Par défaut
    exact, le code mentionné dans le lien que tu donne est erronée. Ce sera le getter() de b qui sera appelé puisque c'est le type de B qui est utilisé.

    Selon les principe d'encapsulation en java, ce n'est pas a toi de choisir si tu va appeler le getter de A ou de B. Si B a redéfini getter() c'est qu'il en a une bonne raison. Si tu veux un objet A qui ne soit pas de type B, il faut faire un new A(), y a pas d'autre chose.

    Comme dit, si tu viens de c++, pratiquement tout les méthodes java sont l'équivalent de virtual en C++. (En java on parle de late binding, pas de virtual). Seules exception, les méthodes final (comme elle peuvent pas etre surchargées par définition, ok), les méthodes privées et les méthodes statique. Ainsi l'exemple que tu donne aurait été vrai dans le cas suivant

    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 A {
        public static void afficher(){System.out.println("A");}
    }
    public class B extends A {
        public static void afficher(){System.out.println("B");}
    }
    A.affiche(); //A
    B.affiche(); //B
    B b = new B();
    b.affiche(); //B
    A a = b;
    a.affiche(); //A
    ((B)a).affiche(); //B

  6. #6
    Membre averti
    Inscrit en
    Mai 2009
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 15
    Par défaut DownCasting
    Merci pour la réponse, les exceptions et l'exemple !

    Je ne viens pas du C++ mais je suis attentif à certains comportements en Java qui échappent à ma compréhension 'basique' des concepts de la POO.

    Par exemple, je suis toujours étonné que l'on puisse faire un downcasting comme dans ton exemple sans se faire jeter par le compilateur.

    Je conçois que cela passe à l'exécution car a contient une référence vers un objet de type B.

    Mais pourquoi le compilateur autorise-t-il un tel cast ?!
    On n'est pas censé caster vers une sous-classe ?!

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2009
    Messages
    21
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Somme (Picardie)

    Informations forums :
    Inscription : Mai 2009
    Messages : 21
    Par défaut
    Citation Envoyé par Nicolas Dansel Voir le message
    Merci pour votre réponse rapide.

    Q1/ Il y a donc un écart entre le code tel qu'on le lit dans l'éditeur et le code réellement exécuté. Je m'en doutais :-) Maintenant, j'en suis sûr.

    Q2/ Disons que j'ai créé un objetB par erreur et que je veux maintenant le déclasser en pur objetA. Comment faire ?

    Le code suivant montre une tentative non concluante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            A objetAbis = new A();
            objetAbis = objetB;
            objetAbis.afficher();
            // => affiche encore 'B' au lieu de 'A' ?!
    Implémente dans A un constructeur prenant en paramètre un objet de classe B, et instanciant l'objet A celon cet objet B, non?

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 01/05/2007, 19h50
  2. Réponses: 3
    Dernier message: 22/02/2007, 21h02
  3. Problème avec une méthode virtuelle pure
    Par Burckel dans le forum C++
    Réponses: 4
    Dernier message: 05/12/2006, 14h00
  4. setTimeout avec une méthode privée
    Par Erakis dans le forum Général JavaScript
    Réponses: 12
    Dernier message: 29/06/2006, 11h47
  5. Non exécution d'une méthode repaint()
    Par Flophx dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 05/05/2006, 19h04

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