Héritage
L'héritage est l'un des quatre piliers fondamentaux de la programmation orientée objet, avec l'encapsulation, l'abstraction et le polymorphisme.
Il permet de créer une nouvelle classe à partir d'une classe existante, en réutilisant ses attributs et ses méthodes, tout en pouvant les spécialiser, étendre ou modifier.
La classe existante est appelée classe mère, classe parente ou superclasse, tandis que la nouvelle classe est appelée classe fille, classe dérivée ou sous-classe.
L'héritage modélise une relation de type « est-un » (is-a).
Objectifs et intérêts de l'héritage
L'héritage répond à plusieurs objectifs essentiels :
Réutilisation du code
Les comportements communs sont définis une seule fois dans la classe parente et partagés par toutes les classes filles.
Factorisation
Les propriétés et méthodes communes sont regroupées dans une classe générique, ce qui réduit les duplications.
Extensibilité
Il est possible d'ajouter de nouveaux comportements sans modifier la classe existante.
Modélisation du réel
L'héritage permet de représenter des hiérarchies naturelles (Animal &rar; Mammifère → Chien).
Vocabulaire fondamental
| Terme | Définition |
|---|---|
| Superclasse | Classe dont on hérite |
| Sous-classe | Classe qui hérite |
| Hériter | Récupérer attributs et méthodes |
| Redéfinition | Modifier le comportement hérité |
| Extension | Ajouter de nouveaux membres |
| super | Accès à la classe parente |
Relation « est-un » (IS-A)
Avant d'utiliser l'héritage, il faut se poser la question :
La classe fille est-elle réellement un type de la classe mère ?
Exemples valides :
- Un Chien est un Animal
- Une Voiture électrique est une Voiture
Exemples invalides :
- Un Moteur est une Voiture
- Une Roulette est une Voiture
Si la relation IS-A n'est pas claire, l'héritage est probablement un mauvais choix.
Structure de base de l'héritage
Classe parente
Voici un exemple en Java :
Classe fille
Voici un exemple en Java :
Utilisation
Voici un exemple en Java :
- Chien chien = new Chien();
- chien.manger(); // méthode héritée
- chien.aboyer(); // méthode spécifique
Héritage et visibilité
Les règles de visibilité influencent directement l'héritage :
| Visibilité | Accessible dans la sous-classe |
|---|---|
| public | Oui |
| protected | Oui |
| private | Non |
Les attributs private ne sont pas directement accessibles dans la sous-classe, mais restent accessibles via des méthodes publiques ou protégées.
Redéfinition de méthodes (Override)
Principe
La redéfinition permet à une sous-classe de modifier le comportement d'une méthode héritée. Voici un exemple en Java :
Règles de redéfinition
- Même signature (nom + paramètres)
- Visibilité identique ou plus large
- Type de retour compatible
- Utilisation recommandée de @Override
Le mot-clef super
Appel d'un constructeur parent
Voici un exemple en Java :
Appel d'une méthode parente
Voici un exemple en Java :
Héritage et constructeurs
- Le constructeur de la classe parente est toujours appelé
- Il est appelé avant celui de la classe fille
- S'il n'est pas appelé explicitement, le constructeur par défaut est invoqué
Héritage simple et multiple
Héritage simple
Un seul parent (Java, C#, PHP).
Héritage multiple
Plusieurs parents (C++, Python).
- class C(A, B):
- pass
Java contourne ce problème via les interfaces.
Problèmes liés à l'héritage
Couplage fort
La sous-classe dépend fortement de la superclasse.
Effet domino
Un changement dans la classe mère peut impacter toutes les classes filles.
Hiérarchies trop profondes
Rend le code difficile à comprendre et à maintenir.
Héritage vs composition
Principe clef : « Préférer la composition à l'héritage »
| Héritage | Composition |
|---|---|
| Relation IS-A | Relation HAS-A |
| Couplage fort | Couplage faible |
| Rigide | Flexible |
| Hiérarchie | Assemblage |
Exemple de composition en Java :
Bonnes pratiques d'héritage
- Utiliser l'héritage uniquement pour des relations IS-A
- Garder les hiérarchies peu profondes
- Ne pas exposer inutilement les détails internes
- Préférer les classes abstraites pour les comportements communs
- Éviter l'héritage pour la simple réutilisation de code
Héritage et conception orientée objet
L'héritage est un outil puissant mais dangereux s'il est mal utilisé. Bien maîtrisé, il permet une modélisation élégante et une forte réutilisation du code. Mal utilisé, il engendre rigidité, complexité et fragilité.
Conclusion
L'héritage permet de partager et spécialiser des comportements, mais il doit être utilisé avec discernement. Une bonne conception orientée objet repose sur un équilibre entre héritage, composition et interfaces.