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
- Il faudrait vérifier les visibilités et notamment vous devriez connaitre le lien entre
protected
et package - On peut empêcher de dériver une classe...
- Il n'y a pas d'héritage multiple en Java même si certains profs peu scrupuleux peuvent faire tout ce qui est en leur pouvoir pour vous induire en erreur.
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.