Héritage, interfaces et polymorphisme
Ce que tu vas apprendre
- Créer une classe qui hérite d'une autre avec
extends. - Définir un contrat avec une
interface. - Utiliser le polymorphisme pour traiter des objets différents de la même façon.
L'héritage
Sur le site de recettes, il existe des plats et des desserts. Un dessert est un plat avec un détail en plus. L'héritage permet de reprendre une classe existante et de l'enrichir.
public class Plat {
protected String nom;
public Plat(String nom) {
this.nom = nom;
}
public String decrire() {
return "Plat : " + nom;
}
}
public class Dessert extends Plat {
private int sucreEnGrammes;
public Dessert(String nom, int sucreEnGrammes) {
super(nom);
this.sucreEnGrammes = sucreEnGrammes;
}
}
extends Plat signifie que Dessert récupère les champs et méthodes de Plat. On parle de classe mère (Plat) et de classe fille (Dessert).
super(nom) appelle le constructeur de la classe mère. Il doit être la première instruction du constructeur.
protected rend un champ visible dans la classe et dans ses classes filles, mais pas ailleurs.
Redéfinir une méthode
La classe fille peut remplacer une méthode héritée. On parle de redéfinition (override).
@Override
public String decrire() {
return "Dessert : " + nom + " (" + sucreEnGrammes + " g de sucre)";
}
L'annotation @Override demande au compilateur de vérifier que la méthode existe bien dans la classe mère. En cas de faute de frappe dans le nom, il signale l'erreur.
Une classe ne peut hériter que d'une seule classe mère. L'héritage sert quand la relation se dit « est un » : un dessert est un plat.
Les interfaces
Une interface décrit ce qu'un objet sait faire, sans dire comment. C'est un contrat.
public interface Notable {
int note();
default String etoiles() {
return "*".repeat(note());
}
}
note() n'a pas de corps : toute classe qui promet cette interface doit l'écrire. Une méthode default fournit au contraire un comportement déjà prêt.
public class Recette implements Notable {
private int note;
public Recette(int note) {
this.note = note;
}
@Override
public int note() {
return note;
}
}
implements indique que la classe respecte le contrat. Contrairement à extends, une classe peut implémenter autant d'interfaces qu'elle veut.
Classe mère (extends) | Interface (implements) | |
|---|---|---|
| Nombre par classe | une seule | autant que nécessaire |
| Peut porter des champs | oui | non, seulement des constantes |
| Sens | « est un » | « sait faire » |
Le polymorphisme
Le polymorphisme (« plusieurs formes ») permet d'utiliser un objet à travers son type parent. La bonne version de la méthode est choisie à l'exécution.
Plat[] menu = {
new Plat("Gratin"),
new Dessert("Tarte", 40)
};
for (Plat p : menu) {
System.out.println(p.decrire());
}
Le tableau contient des Plat, mais il peut y ranger un Dessert. Pour chaque élément, Java appelle la méthode decrire de la vraie classe de l'objet :
Plat : Gratin
Dessert : Tarte (40 g de sucre)
Le code qui parcourt le menu n'a pas besoin de savoir quelle sorte de plat il traite. Ajouter un nouveau type de plat ne demande pas de modifier cette boucle.
Le même principe marche avec les interfaces : une méthode qui prend un Notable accepte n'importe quelle classe qui l'implémente.
Classes abstraites
Une classe abstraite ne peut pas être instanciée avec new. Elle sert de base à d'autres classes et peut contenir des méthodes sans corps.
public abstract class Plat {
public abstract int calories();
}
Toute classe fille non abstraite doit alors écrire calories(). Choisis une interface pour un simple contrat, une classe abstraite quand les classes partagent aussi des champs et du code.
final devant une classe interdit d'en hériter. Avec sealed ... permits ..., tu listes même précisément les classes autorisées à hériter. Cela sert surtout pour le switch expliqué dans le cours 06.Héritage ou composition
L'héritage lie fortement la classe fille à sa mère : modifier l'une peut casser l'autre. Beaucoup de développeurs préfèrent la composition : une Recette possède une liste d'Ingredient au lieu d'en hériter.
À retenir
extendsfait hériter une classe d'une seule classe mère ;super(...)appelle son constructeur.@Overridemarque une méthode redéfinie et fait vérifier le nom par le compilateur.- Une interface est un contrat ; une classe peut en implémenter plusieurs avec
implements. - Le polymorphisme choisit à l'exécution la méthode de la vraie classe de l'objet.
- Quand la relation n'est pas « est un », préfère la composition à l'héritage.
Pour aller plus loin
Sources officielles
Ensuite
Tableaux, classes et records
Stocker plusieurs valeurs dans un tableau, puis modéliser une recette avec une classe, un constructeur, l'encapsulation et un record.
Collections, génériques et exceptions
Manipuler des List et des Map, écrire du code générique, gérer les erreurs avec les exceptions et modéliser des cas avec sealed et switch.
- Projet
- Lignes de code
- Niveau
- Le quartier
- Appartement
- Java
- Pièce
- 5/7
- Plan n°
- java/05.heritage-et-interfaces