Le quartierJV JavaPièce 5/7Intermédiaire

Héritage, interfaces et polymorphisme

Réutiliser une classe avec l'héritage, définir un contrat avec une interface, et traiter des objets différents de la même façon.

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.

Plat.java
public class Plat {
    protected String nom;

    public Plat(String nom) {
        this.nom = nom;
    }

    public String decrire() {
        return "Plat : " + nom;
    }
}
Dessert.java
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).

Dessert.java
@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.

Notable.java
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.

Recette.java
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 classeune seuleautant que nécessaire
Peut porter des champsouinon, 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.

Teste la relation à voix haute. « Un dessert est un plat » : héritage possible. « Une recette a des ingrédients » : composition, donc un champ.

À retenir

  • extends fait hériter une classe d'une seule classe mère ; super(...) appelle son constructeur.
  • @Override marque 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

Projet
Lignes de code
Niveau
Le quartier
Appartement
Java
Pièce
5/7
Plan n°
java/05.heritage-et-interfaces
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.