Programmation orientée objet

Programmation Orientée Objet – Héritage

Paul D

Paul D

4 min

Dans les sections précédentes, nous avons pu voir comment une classe fonctionne, comment ajouter des attributs, des méthodes et comment protéger ces méthodes et attributs. 

Dans cette section, nous allons voir un concept très important en programmation orientée objet: l’héritage.

Le concept d’héritage


L’héritage en programmation orientée objet permet de créer facilement des classes similaires à partir d’une autre classe. On parle alors de faire hériter une classe fille d’une classe mère. Dans notre exemple de la classe Animal, on va pouvoir faire hériter des classes Reptile, Mammifère ou Oiseau de la class Animal: on continue de construire des classes, et donc des modèles pour des objets, mais ces classes filles vont avoir les attributs et méthodes de la classe mère et des attributs et des méthodes spécifiques à ces classes filles. 

Dans notre exemple, la classe Animal avait un attribut age et un attribut nom, une méthode nommer et un méthode vieillir. Les classes filles de la classe Animal auront ces mêmes méthodes et ces mêmes attributs mais elles pourront aussi en avoir d’autres. 

Pour faire une analogie avec la biologie, on peut rapprocher la construction de lien d’héritage entre classes de la construction d’un arbre phylogénétique. 

heritage poo
Un arbre comme celui-ci représente les liens évolutifs entre différents groupes d’êtres vivants (PS: on est dans le rose)

L’héritage permet ainsi de simplifier considérablement l’écriture du code: imaginez construire une application pour une école. Vous avez besoin de modéliser des utilisateurs avec des informations très similaires (noms, prénoms, date de naissance). Mais certains utilisateurs vont pouvoir faire des actions plus spécifiques. On peut donc construire une classe Utilisateur, puis faire hériter deux classes: Elèves et Personnel. On pourra même faire hériter des classes Professeur, Assistant, Documentaliste, … de la classe Personnel. En terme de développement on évite de refaire le travail complet à chaque nouvelle classe.

L’héritage avec Python

Essayons de construire une classe Reptile qui hérite de la classe Animal. Pour cela, on va déclarer une classe Reptile et indiquer, juste après le nom de la classe fille, le nom de la classe mère entre parenthèses.

Dans cet exemple, on voit bien que l’objet reptile est une instance de la classe Reptile mais qu’il a conservé les méthodes et attributs de la classe Animal sans qu’on ait besoin de les redéfinir: c’est toute la force de l’héritage.

Polymorphisme

On peut toutefois vouloir qu’une méthode d’une classe fille n’ait pas le même comportement que son équivalent dans la classe mère. On redéfinit alors simplement la méthode dans la classe fille. On parle de polymorphisme et cette technique relève de la surcharge de méthode, ou en anglais overriding.

Attention, le polymorphisme peut désigner deux choses différentes: le fait de définir des méthodes différentes pour des classes qui héritent l’une de l’autre (overriding) mais aussi le fait de définir plusieurs fois la même méthode (ou fonction) avec des arguments différents (overloading). Le second cas est plus naturel dans des langages de programmation typé statiquement (Java, C++, …) et est assez éloigné de la philosophie de Python. Nous n’en parlerons donc pas ici.

Pour en savoir plus sur le type des données en Python, découvrez cet article.

Tentons de surcharger la méthode nommer de l’exemple précédent:

Dans cet exemple, on a juste ajouter une impression dans la méthode nommer mais la méthode fait bien la même chose. 

Essayons à présent de surcharger la méthode __init__, pour lui donner de nouveaux attributs. Le problème est que les instructions donnés dans la méthode __init__ de la classe Animal sont toujours bonnes. On voudrait bien ne pas avoir à tout recoder juste pour ajouter un attribut. En fait, on peut faire appel à la méthode de la classe mère en utilisant le mot-clef super.

On voit dans cet exemple que lors de l’instanciation, on fait bien appelle à la méthode __init__ de la classe Animal puis on ajoute quelques instructions qui sont spécifiques à la classe Reptile

Notez qu’on peut enchaîner les appels à la méthode de la classe mère grâce au mot clef super.

Héritages multiples

Jusqu’à présent, nous avons vu l’héritage dans le cas d’une classe mère et de plusieurs classes filles. Mais on peut aussi avoir plusieurs classes mère pour une classe fille. 

Mais pourquoi vouloir faire hériter une classe de plusieurs classes mère? encore une fois il s’agit d’une question de simplicité du code: si une classe contient certaines fonctionnalités (authentification par exemple) et une autre d’autres fonctionnalités (modèle de Machine Learning) alors on peut vouloir les propriétés de ces deux classes pour une classe fille: par exemple, une voiture de fonction est à la fois un véhicule avec des caractéristiques propres à un véhicule mais c’est aussi un bien de l’entreprise avec des caractéristiques comptables qui lui sont propres.

Attention: 

Dans Java par exemple, on ne peut pas avoir une classe qui hérite de plusieurs classes mères (au même niveau). On utilise alors un autre outil, les interfaces, qui permettent ces héritages multiples. Cependant on dit que la classe fille implémente une interface. En Python, on s’en fiche.

On retrouve beaucoup de ces exemples dans le module sklearn.  Puisqu’il y a plusieurs classes mère, il suffit simplement de les signaler toutes .

Pourtant si vous faîtes tourner cet exemple, vous allez voir qu’on n’imprime pas l’instanciation de B… La fonction super ne prend en compte que la première class mère. Heureusement, il existe une autre méthode pour faire appel à la méthode de la classe mère:

Cette autre méthode permet d’être sûr de la méthode mère à laquelle on fait référence. Ici on a ajouté des attributs différents pour chacune des classes pour vérifier que l’instanciation se faisait bien. Mais que se passe-t-il si des attributs ont le même nom ? En fait, tout dépend simplement de l’ordre dans lequel on fait appel aux méthodes des classes mère.

Attributs et méthodes protégés

On a déjà vu beaucoup de choses sur ce concept d’héritage. On va s’arrêter pour le moment en revenant très rapidement sur la section précédente: nous avions alors parlé d’attributs privés, c’est-à-dire accessibles uniquement à l’intérieur de la définition de la classe, d’attributs publics accessibles absolument partout. Nous avions aussi fait le silence sur le concept d’attributs protégés: en programmation orientée objet, les attributs sont accessibles à l’intérieur de la définition de la classe ainsi que dans celles de toutes les classes qui en hérite (directement ou indirectement). Ce concept n’a, par contre, pas vraiment de sens en Python.

Dans cette section, nous avons vu un des concepts les plus importants de la Programmation Orientée Objet: l’héritage. En permettant de s’inspirer de définitions précédentes, l’héritage permet de gagner un certain temps de développement. Dans la prochaine section, nous évoquerons les notions de classes abstraites ainsi que de méthodes et attributs statiques

Actualité data

DataScientist : Recrutement VS Formation

Pour la 5ème année consécutive, le métier de Data Scientist a été désigné comme le meilleur emploi aux USA par Glassdoor c’est aussi le métier qui connaît la croissance la plus rapide.

Lire plus »
Intelligence Artificielle et Société

Ethique ou Big Data

Comment faire prévaloir une question d’éthique en matière de données alors que la concurrence se veut mondiale ? Les européens doivent-ils se soumettre à une concurrence américaine et asiatique déloyale pour une question d’éthique ?

Lire plus »