Copy of https://perso.isima.fr/loic/java/exo_jse_base_heritage.php
tete du loic

 Loïc YON [KIUX]

  • Enseignant-chercheur
  • Référent Formation Continue
  • Responsable des contrats pros ingénieur
  • Référent entrepreneuriat
  • Responsable de la filière F2 ingénieur
  • Secouriste Sauveteur du Travail
mail
loic.yon@isima.fr
phone
(+33 / 0) 4 73 40 50 42
location_on
Institut d'informatique ISIMA
  • twitter
  • linkedin
  • viadeo

[JavaSE] Héritage

 Cette page commence à dater. Son contenu n'est peut-être plus à jour. Contactez-moi si c'est le cas!

Date de première publication : 2021/10/13

Vous allez découvrir

L'héritage

L'héritage, à l'origine, a permis d'éviter la duplication de code.

Si une classe Mere est dotée d'une méthode m()


class Mere {
  public void m() {
     System.out.println("methode de mere"+);
  }
}

Une classe fille ...


class Fille extends Mere {
}

... l'aura aussi, par héritage ...


public class Heritage {
  public static void main(String[]) {
      Fille f = new Fille();
      f.m();
  }
}

Vous l'avez compris, pour voir cela, on a mis toutes les classes dans un fichier Heritage.java

Une classe hérite de tous les attributs publics et protégés sauf des constructeurs. Nous allons le vérifier de suite

Vous pouvez ajouter un attribut protégé nom de type String à la classe mère.


class Mere {
  protected String nom;

  public void m() {
     System.out.println("Je suis ta mere ["+nom+"]");
  }
}

Cet attribut est directement accessible dans la classe fille.


class Fille extends Mere {
  public Fille() {
     System.out.println("construction de fille");
     nom = "fille";
  }
}

La construction des objets

On va maintenant vérifier que construire un objet de classe fille construit bien un objet de classe mère même si on ne fait rien ... Pour cela, il faut simplement ajouter un constructeur sans argument à la classe mère :


class Mere {
  protected String nom;

  public M() { 
    System.out.println("Construction de mere par defaut");
  }
}

Si vous le voulez, vous pouvez spécifier l'appel au constructeur sans argument avec l'appel à super(); en première ligne. Mais si vous ne le faites pas, c'est fait quand même.

Si vous ajoutez un constructeur avec argument à la classe mère pour initialiser l'attribut nom, vous pouvez vérifier qu'il n'est pas hérité :


public class Heritage {
  public static void main(String[]) {
      Fille f = new Fille("essai");
      f.m();
  }
}

Ecrivez le constructeur de la classe fille qui ferait marcher le code précédent ... Comment appeler le bon constructeur de Mere et que ce passe-t-il si le bon constructeur de Mere n'est pas appelé ?

Le polymorphisme

Le polymorphisme fort ou overriding permet de redéfinir une méthode dans une hiérarchie.

La détermination de la bonne méthode se fait à l'exécution pas à la compilation, c'est pour cela que l'on dit que la méthode est virtuelle !

Ce processus de détermination peut être assez long car il implique la création d'une structure de données appelée table des méthodes virtuelles et le parcours de la dite table pour trouver la bonne version de la méthode. Cependant la machine virtuelle java peut être redoutablement efficace.


class Fille extends Mere {
  public void m() {
     System.out.println("methode de fille"+);
  }
}

Qu'est-ce que donne maintenant le appel de f.m(); ?

Dans le cas présent, on a complètement changé le code de la méthode m() mais on peut faire appel au code de la classe mère comme on veut :-)


super.m();

Pour finir, une bonne pratique est de doter la méthode redéfinie d'une annotation. Cela permet de prévenir la personne qui lit le code et surtout le compilateur qui va vérifier que la méthode est bien une rédéfinition...


class Fille extends Mere {
  @Override
  public void M() {
     System.out.println("methode de fille"+);
  }
}

Toutes les méthodes en Java sont virtuelles par défaut et peuvent donc être redéfinies. Si vous ne voulez pas que ce soit le cas, il ne faut pas hésiter à les déclarer final.


class Mere {
  protected String nom;

  final public void m() {
     System.out.println("Je suis ta mere ["+nom+"]");
  }
}

Quand on utilise des méthodes finales, on coupe la recherche dans la table des méthodes virtuelles, donc elles sont plus rapides à trouver. Ceci dit, il existe des optimisations de la machine virtuelle qui sont encore plus redoutables que cela ... et de loin...

Ultimes remarques

Encapsulation

Pour finir, j'aime bien garder les attributs de la classe mère private et non protected. Je suis un intégriste de l'encapsulation : seules les méthodes de la classe mère permettent d'accéder aux attributs spécifiques de la classe mère.