Partage
  • Partager sur Facebook
  • Partager sur Twitter

Question sur l'héritage

    20 septembre 2017 à 22:45:35

    Bonjour, 

    Je ne comprend pas quelque chose au sujet de l'héritage, voilà la situation :

    J'ai une classe Parent :

    public class Parent {
      protected int v;
      void truc() {
        System.out.println("parent");
        v++;
      }
    }

    Une classe Child :

    public class Child extends Parent{
      private int v;
      void truc() {
        System.out.println("enfant");
        v++;
      }
    }

    Et une classe Main :

    public class Main {
      public static void main(String[] args) {
        Parent x;
        x = new Child();
        x.truc();
        System.out.println(x.v);
      }
    }

    J'ai pour résultat : 

    enfant
    0

    Pourquoi v ne s'incrémente pas ? 

    Merci d'avance, bonne soirée.





    • Partager sur Facebook
    • Partager sur Twitter
      21 septembre 2017 à 0:07:01

      La visibilité de v dans la classe Child est privée et tu y accèdes sans getter.
      • Partager sur Facebook
      • Partager sur Twitter
        21 septembre 2017 à 0:12:07

        Tu n'aurais pas dû redéclarer "v" dans ta classe "Child". Sachant que tu as mis "v" de ta classe "Parent" en protected, ta classe fils y accède aussi.
        J'aurais cru que le générateur aurait signalé une erreur en déclarant la même variable dans le père et le fils.
        • Partager sur Facebook
        • Partager sur Twitter
          21 septembre 2017 à 0:16:03

          Redéclarer v dans la classe Child permet ici de changer la visibilité de l'attribut "v". Il n'y a rien de choquant étant donné que le principe de substitution s'applique.
          • Partager sur Facebook
          • Partager sur Twitter
            21 septembre 2017 à 8:14:11

            Bonjour,

            Voici ce qui se passe dans ton code. Tu as deux attributs "v" :

            • 1 protected dans la classe parent
            • 1 private dans la classe Child

            Ce sont bien deux attributs différents, pas juste une changement de visibilité !

            La variable x est de type Parent mais pointe vers un objet de type Child. Quand tu appelles "x.truc()", c'est la méthode du type "réel" de l'objet (Child) qui est appelée. Elle incrémente donc le v de Child.

            Par contre, quand tu affiches v, c'est le v de Parent qui s'affiche. Pourquoi ?

            Parce que v de Child est private. Il est donc inaccessible en dehors de la classe Child. Rien à voir avec les getters, désolé OncleBens :p.

            Donc c'est le v de Parent qui s'affiche puisqu'il a l'accès protected et j'imagine que Main et Parent sont dans le même package.

            D'ailleurs, sans le v de Parent ou si Main était dans un autre package, le code ne compilerait même pas.

            Moralité,

            • Eviter les attribut protected. On peut toujours s'en passer. Avec private, tu es sûr de faire le bon choix.
            • Quand tu crées des attributs avec des noms identiques, c'est la porte ouverte aux bugs tordus à corriger (comme ici). Donc à éviter aussi.

            -
            Edité par brubru777 21 septembre 2017 à 8:16:35

            • Partager sur Facebook
            • Partager sur Twitter
              21 septembre 2017 à 22:29:47

              D'accord mais même en le mettant en public il m'affiche tout de même 0. :(
              • Partager sur Facebook
              • Partager sur Twitter
                21 septembre 2017 à 22:59:37

                Si tu déclares x comme Parent, ça affiche 0.

                Si tu déclares x comme Child, ça affiche 1.

                On peut en déduire que pour les attributs, contrairement aux méthodes, Java choisit l'attribut de la classe déclarée pas de la classe "réelle" de l'objet.

                Raison de plus de mettre les attributs private et de ne pas en déclarer plusieurs avec le même nom.

                • Partager sur Facebook
                • Partager sur Twitter
                  22 septembre 2017 à 9:30:34

                  Petit conseil : sur les variables/methodes/operations que tu veux redefinir (ecraser celle du parent avec l'enfant), met un @Override avant la methode ou variable. Ca indique au compilateur et au debugueur d'eclipse ton intention. Et te genere donc une erreur si c'est bien fait ou pas :p. PAr exemple protected -> private ne fonctionne pas pour un Override.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  @autor VinYarD

                  Question sur l'héritage

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown