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

avec Java Discussion :

Cas particulier héritage


Sujet :

avec Java

  1. #1
    Membre à l'essai
    Profil pro
    Ingénieur
    Inscrit en
    Mars 2004
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Mars 2004
    Messages : 20
    Points : 11
    Points
    11
    Par défaut Cas particulier héritage
    Bonjour,

    Je vais bientôt passer un examen sur papier en Java, et le prof aime bien nous coller des cas tordus et nous demander, pour chaque ligne, si ça compile, et si oui qu'est ce qui se passe et pourquoi. Voici un exemple de code qui me pose problème :

    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
     
    interface I1 {
       int m1();
    }
    interface I2 extends I1 {
       int m2();
    }
    class B implements I1 {
       int i = 7;
       public int m1() { return i; }
    }
    class C extends B implements I2 {
       int i = -7;
       public int m1() { return i; }
       public int m2() { return i; }
    }
    public class Test {
       public static void main(String[] args) {
          B x = new C();
          System.out.println(x.i); // Affiche 7
          System.out.println(x.m1()); // Affiche -7
          // System.out.println(x.m2()); // Ne compile pas
       }
    }
    J'y ai ajouté mes commentaires pour dire ce qu'il se passe à l'exécution. Sauriez vous m'expliquer ce qu'il se passe lors de l'éxécution dans la machine virtuelle ? Quelles méthodes sont appelées, celles de B ou de C (visiblement celles de B vu que x.m2() ne compile pas). Ou et comment les valeurs 7 ou -7 sont elles piochées.

    Si quelqu'un pouvait m'aider à comprendre ceci, ça m'aiderait beaucoup.
    Kakashi_sensei

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    pour les appels de méthode, c'est l'instance réelle à l'exécution qui est utilisées en général (sauf pour les cas où le early binding s'applique, c'est à dire les méthode statiques et les méthodes final). voilà pour m1. Par contre, ca ne peut pas compiler si la méthode n'existe pas dans le type déclaré (voilà pour m2). Pour le champ, c'est le type déclaré qui est utilisé.

  3. #3
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Je suis consterné de voir des étudiants se prendre la tête avec des problèmes aussi ridicules, mais enfin...

    Pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println(x.i); // Affiche 7
    ... cela me parait tout à fait étrange... x, si je suis bien, est déclaré de la classe B, mais il est de la classe C, i dans ces deux classes est une variable d'instance, donc c'est C qui compte, i dans C vaut -7 et non 7 ; donc je comprends pas.

    Pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println(x.m1()); // Affiche -7
    Là ça va : x appelle m1 de C (on passe sur la prétendue redéfinition destinée uniquement à ce que le prof puisse faire le malin si un élève se plante), qui va chercher le i qui étant une variable d'instance est à -7.

    Enfin pour
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          // System.out.println(x.m2()); // Ne compile pas
    cela ne compile pas, bien que il existe une méthode m2 dans la classe de C est que l'objet soit de classe C, parce que la déclaration de l'objet x est de classe B qui ne contient pas de méthode m2 (vous suivez ?... sinon c'est pas grave ça ne sert absolument à rien et c'est même nuisible dans le monde professionnel). À la compilation il faut suivre les déclarations, mais à l'exécution il faut suivre les classes.

    C'est de la m*** intellectuelle.
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    Je suis consterné de voir des étudiants se prendre la tête avec des problèmes aussi ridicules, mais enfin...
    ca n'a rien de ridicule et pour répondre à ces question, il est nécessaire d'avoir compris le fonctionnement de java, ce test me semble au contraire très approprié pour savior si un étudiant a bien compris le language et surtout la portée des concepts de bases comme l'héritage, l'overriding et la visiblité.
    Citation Envoyé par gifffftane Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println(x.i); // Affiche 7
    ... cela me parait tout à fait étrange... x, si je suis bien, est déclaré de la classe B, mais il est de la classe C, i dans ces deux classes est une variable d'instance, donc c'est C qui compte, i dans C vaut -7 et non 7 ; donc je comprends pas.
    Contrairement aux méthodes, il n'y a pas de notion de redéfinition des champs d'une classe. En pratique, ca veux dire que les accès aux champs se font en early-binding. Le compilateur calcule l'accès au champ en fonction du type déclaré et rien ne change à l'exécution. C'est le même principe qui est d'ailleurs appliqué pour l'accès aux méthodes statiques. On aurait d'ailleurs pour pousser le vice en faisant de i un String ou un List dans C sans pour autant que ca gene le compilateur.

  5. #5
    Membre à l'essai
    Profil pro
    Ingénieur
    Inscrit en
    Mars 2004
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Mars 2004
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Je vous remercie de vos réponses, ça éclaire ma lanterne. Je suis complètement d'accord avec toi gifffftane par ailleurs, c'est des problèmes assez absurdes. Cela dit, le jour ou je devrais me taper une TMA d'une application mal codée (ce qui est toujours le cas des TMA :p) et que je tombe sur des bouts de code comme ça, je saurais peut être à quoi m'attendre. EDIT : et comme le dit tchize ça me permet de comprendre en profondeur le fonctionnement de Java, donc ça peut pas faire de mal

    Pour résumer, si j'ai bien compris :
    A l'exécution, un appel de méthode appelle la méthode de la classe instanciée sauf si cette méthode est statique (ce qui parait logique) ou final.
    Un accès à une variable fait référence à la variable de la classe déclarée.
    Enfin, à la compilation, c'est la classe déclarée qui est vérifiée pour les appels de méthodes.

    C'est bien ça ?
    Kakashi_sensei

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Kakashi_sensei Voir le message
    A l'exécution, un appel de méthode appelle la méthode de la classe instanciée sauf si cette méthode est statique (ce qui parait logique) ou final.
    ou private

  7. #7
    Membre à l'essai
    Profil pro
    Ingénieur
    Inscrit en
    Mars 2004
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Mars 2004
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    quand tu dis "lorsque la méthode est final ou private", tu veux dire dans la classe mère ?

    Parce que pour final, si la méthode n'est final que dans C, elle est overridée n'est ce pas ?
    Quand à une méthode private : override-t-elle la méthode de la classe mère ? genre si m1() était private dans C ? Bon en fait je viens de tester, ça ne semble pas être possible :
    Test.java:35: m1() in C cannot override m1() in B; attempting to assign weaker access privileges; was public private int m1(){

    PS : après test je rajouterai "ou non définie dans la classe fille" à la liste "si la méthode est statique, ou final, ou private"
    Kakashi_sensei

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    pour les méthodes private, c'est toujours le type déclaré qui compte. Ainsi, dans le code suivante

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class A {
       private int m1(){return 1;}
       public int m() {return m1();}
    }public class B extends A {
       private int m1(){return 2;}
    }
    ....
    B b = new B();
    System.out.println(b.m());//affiche 1
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class A {
       protected int m1(){return 1;}
       public int m() {return m1();}
    }public class B extends A {
       protected int m1(){return 2;}
    }
    ....
    B b = new B();
    System.out.println(b.m());//affiche 2
    Dans le premier cas l'appel à m1 dépend du type d'éclaré (là, implicitement "this" qui est de type déclaré A) mais dans le deuxième cas ca dépend du type runtime (là, implicitément de "this" qui en runtime de type B)

    ca reviens à dire qu'un méthode privée ne peux pas être overridée par un fils alors qu'un méthode non privée peut l'être

  9. #9
    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 tchize_ Voir le message
    ca reviens à dire qu'un méthode privée ne peux pas être overridée par un fils alors qu'un méthode non privée peut l'être
    C'est tout à fait cela : une méthode non-privé peut éventuellement être redéfini dans une classe fille, et donc le compilateur génère un appel de type "invokevirtual" qui indique à la JVM qu'elle devra vérifier le type exact de l'instance pour vérifier qu'il n'y ait pas une redéfinition...
    C'est le principe même du polymorphisme par dérivation !



    Les méthodes privés ne pouvant pas être redéfinies, le compilateur génèrera alors un appel de type "invokespecial" qui indique à la JVM d'appeler directement la méthode sans mécanisme de polymorphisme. Au passage c'est le même type d'appel qui est utilisé lorsqu'on appelle une méthode de la classe parente via super.m() par exemple...


    a++

  10. #10
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    ca n'a rien de ridicule et pour répondre à ces question, il est nécessaire d'avoir compris le fonctionnement de java, ce test me semble au contraire très approprié pour savior si un étudiant a bien compris le language et surtout la portée des concepts de bases comme l'héritage, l'overriding et la visiblité.
    Ce n'est pas parce que l'on sait couper des cheveux en 4 que l'on sait faire de la couture, ni qu'on a compris le fonctionnement des ciseaux. Tout au plus sait-on compter jusqu'à 4, et il existe des méthodes beaucoup plus efficaces pour y parvenir.

    Pour comprendre quelque chose, mon opinion est qu'il n'y a rien de mieux que les cas simples, mais significatifs ; les cas compliqués exercent seulement à démeler les...complications - c'est un jeu intellectuel, et à sa suite on n'a rien compris de plus.

    C'est comme la belle-mère du beau père de la grand tante du général de l'échelon inférieur au capitaine de corvette de l'armée des indes, le trouver ne permet pas de comprendre ce qu'est une famille.

    Et puis surtout en informatique - et en java particulièrement - il me semble qu'il vaut mieux passer du temps à exprimer un contexte donné - je veux dire autre chose que des classes A, B et C - (qui ne parviennent même pas à exprimer l'alphabet), plutot qu'à des prises de têtes.

    Il t'es souvent arrivé, à toi, de nommer à l'identique et redéfinir des attributs dans une hiérarchie de classe ? Et si tu le fais ça te permet de mieux comprendre quoi ?

    Moi, quand je vais en Irlande, je parle 15 fois mieux anglais au bout de deux bières, c'est pareil en Java et je conseille cette méthode à tout le monde

    (j'ai dit DEUX bières, hein, pas 20).
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  11. #11
    Membre à l'essai
    Profil pro
    Ingénieur
    Inscrit en
    Mars 2004
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur

    Informations forums :
    Inscription : Mars 2004
    Messages : 20
    Points : 11
    Points
    11
    Par défaut
    Lol, au final, ce petit bout de code, avec quelques experts pour en parler, me permet quand même de comprendre dans les détails le fonctionnement de la JVM ce dont on ne parle rarement quand on parle du concept global d'héritage.

    Ce n'est peut être pas ce bout de code qui me permet de comprendre le concept de l'héritage et du polymorphisme, mais c'est plutôt des questions qui quand on prend le temps de se les poser, permettent d'approfondir le sujet et de savoir ce qu'il se passe dans tous les cas.

    Après c'est sur qu'il faut avoir en tête que si l'on faisait un code propre dès le départ, on ne tomberait peut être pas sur ces cas tordus. Mais en partant du principe que l'on ne maitrise pas le code écrit par les millions d'autres développeurs, qu'on est susceptibles de devoir retoucher un jour, autant comprendre tous les cas possibles.

    Ce n'est que mon avis de débutant, surtout que je sais que je vais avoir un maximum de cas alambiqués pendant l'exam, ce qui me motive à poser ce genre de questions.

    En tout cas je pense qu'on est tous d'accord pour aller se boire une biere, hein
    Kakashi_sensei

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    le cas de ton i peut très bien se poser en production meme en code propre. Quand tu écrit le code d'un classe java, tu ne regarde jamais les champs de ta classe parent, qu'ils soient privés ou public. Il est bon de savoir que tu peux écrire ta classe sans t"en soucier, tes champs à toi ne pourront pas clasher avec les champs de ton parent.

    Pour l'appel de méthode, ton prof aurarit peut etre eu plsu judicieux à faire le cas de la méthode statique. Combien de fois j'ai pas vu des gens se lancer dans du code java pour se rendre compte après de longs développement que... non, ils ne peuvent pas se baser sur un polymorphisme d'héritage avec des méthodes statiques.

Discussions similaires

  1. Incompréhension d'un cas particulier d'héritage
    Par backlash dans le forum Langage
    Réponses: 8
    Dernier message: 18/12/2011, 04h08
  2. Réponses: 27
    Dernier message: 12/01/2006, 11h04
  3. cas particulier agaçant
    Par devdébuto dans le forum C
    Réponses: 17
    Dernier message: 13/12/2005, 23h45
  4. Enregistrement courant après refresh [cas particulier]
    Par say dans le forum Bases de données
    Réponses: 8
    Dernier message: 02/08/2005, 15h59

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