Dans cette article, nous allons découvrir les bases de la Programmation Orientée Objet (POO), avec les notions de classe et d'héritage, puis nous allons voir comment implémenter cela en Python.
La POO est un paradigme de programmation qui consiste à diviser son code en rassemblant des propriétés et des comportements dans des classes afin de former des objets.
Des objets sont comme des composants d'un système complexe. Chaque objet remplit une ou plusieurs fonctions, et la coordination entre ces objets permet de faire fonctionner le programme. Par exemple, si on reprend le jeu de morpion traité dans cet article : Exercice - Jeu de Morpion, on peut diviser le programme en différents objets :
Plateau
: correspond au plateau du jeu, et contient des méthodes pour le dessiner, le mettre à jour, etc...Ordinateur
: correspond à l'ordinateur, et contient une méthode pour choisir une case aléatoire du plateau.Joueur
: correspond au joueur, et contient une méthode pour demander sur quelle case jouer.En fait, la POO est une façon de modéliser le monde réel et les interactions entre les différents éléments, par exemple on peut créer un objet Voiture
et modéliser ses interactions avec un objet Parking
.
Une classe est ce qui permet de fabriquer un objet, c'est comme un plan. On dit donc qu'on objet est une instance d'une classe. Imaginons que vous souhaitez modéliser une personne. Il faut donc créer la classe Personne
, et ensuite vous pourrez instancier plusieurs personnes, par exemple avec des noms ou des âges différents. Ainsi, Personne
est une classe et John
est une instance de cette classe.
Pour créer une classe, on utilise la mot-clé class
suivi du nom de la classe et de :
. Par exemple, pour créer une classe Personne
:
class Personne:
Cependant, ce code ne fonctionnera pas en Python car vous ne pouvez pas créer de classe sans déclarer d'attributs. Pour rappel, les attributs sont des variables appartenant à la classe. Dans notre cas, on peut donner un nom, un prénom, un âge, un sexe… à une personne. Pour cela, on a besoin de la méthode spéciale __init__
.
Comme évoqué plus haut, cette méthode est une méthode spéciale. Pour rappel, une méthode est une fonction appartenant à une classe. Les méthodes spéciales sont des méthodes permettant à un objet d'avoir des comportements particuliers. Ici, la méthode __init__
permet de définir un constructeur pour notre classe, c'est à dire que lorsqu'on créera un objet, la méthode __init__
sera appelée. Cette méthode est générique et c'est la seule méthode permettant de définir un constructeur, donc vous êtes obligés de la coder dans chaque classe que vous réalisez. Comme toute fonction, on peut y passer des paramètres et les utiliser dans le corps de la classe. On peut par exemple lui passer les paramètres nom
, prenom
, age
etc... afin de construire un objet Personne
avec ces attributs. Avant d'écrire cette méthode pour notre classe, il est cependant nécessaire de voir le mot-clé self
.
Lorsque l'on utilise une instance d'une classe, il est nécessaire de différencier les attributs qui appartiennent à la classe, des paramètres utilisés dans les méthodes. Par exemple, en reprenant l'exemple de la classe Personne
, on sait que cette classe possède un attribut nom
. Comment je peux accéder à cet attribut depuis l'intérieur de ma classe ? C'est là qu'il faut utiliser le mot-clé self
. En utilisant self.nom
dans ma classe, je peux accéder à l'attribut nom
. Mais pour utiliser ce mot-clé, il est nécessaire de le passer en premier paramètre de la méthode dans laquelle on souhaite l'utiliser. On peut maintenance écrire notre méthode __init__
qui sera donc le constructeur de notre classe Personne
.
def __init__(self, nom, prenom, age):
self.nom = nom
self.prenom = prenom
self.age = age
On passe self
en premier paramètre afin de pouvoir déclarer nos attributs via self.nom
, self.prenom
et self.age
.
Notre classe Personne
ressemble donc à ceci maintenant :
class Personne:
def __init__(self, nom, prenom, age):
self.nom = nom
self.prenom = prenom
self.age = age
Et on peut donc créer un objet Personne
maintenant !
Afin d'instancier une classe, il faut utiliser le constructeur défini dans la classe que l'on souhaite instancier. Dans notre exemple, on passe 3 paramètres au constructeur de Personne
(en réalité 4, mais self
est un paramètre faisant référence à l'objet lui-même). On doit donc forcément passer ces paramètres lorsque l'on instancie une classe Personne
. Voici comment créer un objet Personne
.
>>> jean = Personne("Dupont", "Jean", 41)
>>> jean
<__main__.Personne object at 0x000001DEC4770040>
Lorsque l'on souhaite afficher notre objet, on obtient une drôle de ligne. C'est l'affichage par défaut de tout objet. Heureusement, il existe une méthode spéciale pour modifier cet affichage. Il s'agit de la méthode __repr__
. Elle ne prend aucun paramètre (sauf self
afin d'accéder à l'objet que l'on souhaite afficher) et renvoie une chaine de caractères qui est le texte que vous voyez lorsque vous affichez votre objet via l'interpréteur ou la fonction print
. Essayez d'implémenter cette fonction dans notre classe Personne
, de sorte qu'on obtienne le résultat suivant, c'est un petit entraînement pour voir si vous avez compris ce qu'on a vu jusque là :
>>> jean = Personne("Dupont", "Jean", 41)
>>> jean
Je m'appelle Jean !
Maintenant que notre objet est créé, on aimerait interagir avec, il faut donc implémenter des méthodes.
Normalement, vous savez déjà implémenter des méthodes. En effet, nous avons toute à l'heure implémenté des méthodes spéciales, l'implémentation de méthodes classiques est tout à fait similaire. La seule différence est que l'appel à ces méthodes se fait différemment. Voici la syntaxe : objet.methode(parametre1, parametre2, ...)
. Par exemple, si on crée une méthode discuter pour notre classe Personne
qui prend en paramètre une chaine de caractères, on appellera cette méthode de cette façon :
jean.discuter("Bonjour !") # jean est une instance de Personne
D'ailleurs, puisque vous savez déjà implémenter des méthodes, vous devriez réussir à implémenter celle-ci dans notre classe Personne
, de sorte que l'on obtienne ceci :
>>> jean.discuter("Bonjour")
Jean a dit : 'Bonjour !'
Maintenant vous savez créer des classes basiques ! Nous pouvons donc attaquer la notion d'héritage.
L'héritage est une notion fondamentale de la Programmation Orientée Objet, permettant de créer une nouvelle classe en se basant sur une classe existante. Cela permet de spécialiser une classe existante sans avoir à tout réécrire. Cela permet aussi la création de classes abstraites dont nous parlerons plus tard.
Pour comprendre la notion d'héritage, reprenons notre classe Personne
. Elle modélise une personne, sans réelle spécificité. Et si nous souhaitons modéliser un employé par exemple. Un employé est d'un point de vue POO une spécialisation d'une personne, puisqu'il a, en plus des attributs d'une personne, un salaire, et une entreprise pour laquelle il travaille. Le mieux à faire est donc de faire hériter notre classe Employe
de la classe Personne
, ainsi notre nouvelle classe aura accès aux attributs et méthodes de la classe Personne
appelée classe parente, et on pourra même définir de nouveaux attributs et de nouvelles méthodes spécifiques à notre classe Employe
, c'est ce que nous allons faire maintenant !
Pour créer une classe héritant d'une autre classe en Python, on le précise lors de la définition de la classe de cette façon :
class nom_classe(nom_classe_parente):
On précise entre parenthèses la classe parente.
Appliqué à notre exemple, ce code devient :
classe Employe(Personne):
Maintenant, il faut définir un constructeur. En effet, vous vous rappelez, je vous ai dit que pour toute classe il faut définir un constructeur, cela est valable aussi pour les classes héritant d'autres classes. On aurait pu penser que s'il n'y a pas de constructeur, on prend celui par défaut de la classe parente, mais ce n'est pas le cas en Python !
Dans notre exemple, un employé est une personne, possédant en plus un salaire et une entreprise. On peut donc utiliser le constructeur de la classe Personne
, et y rajouter deux paramètres pour le salaire et l'entreprise. Pour faire ceci, nous allons avoir besoin de la fonction super
.
C'est une fonction très puissante, très utilisée dès qu'on touche à l'héritage, qui permet d'appeler la classe parente.
En effet, en appelant super
, on fait référence à la classe parente, et on peut donc récupérer ses méthodes. Par exemple, pour récupérer le constructeur de la classe parente, on utilise super().__init__
.
On peut maintenant revenir à notre classe Employe
, et écrire notre constructeur.
# classe Employe
def __init__(self, nom, prenom, age, salaire, entreprise):
super().__init__(nom, prenom, age)
self.salaire = salaire
self.entreprise = entreprise
Quelques explications sur ce code : on a besoin maintenant de 5 paramètres dans notre constructeur, puisqu'on définit en plus des attributs de base des attributs pour le salaire et l'entreprise. Ensuite, on appelle le constructeur de la classe parente, en utilisant super
. On lui passe les paramètres correspondants, donc nom
, prenom
et age
. Et ensuite on rajoute la déclaration des attributs spécifiques à notre classe Employe
.
Comme nous l'avons fait pour le constructeur de la classe, nous pouvons redéfinir n'importe quelle méthode, et même en ajouter des nouvelles.
Pour en redéfinir, il suffit de les réécrire, et de modifier leur code. Pour en rajouter, il suffit de définir de nouvelles méthodes. Vous savez déjà tout ! Essayez donc de redéfinir la méthode discuter
pour afficher l'entreprise à côté du nom de la personne, et la méthode __repr__
pour afficher en plus le salaire.
Pour accéder aux attributs de la classe parente depuis l'intérieur de la classe enfant, vous pouvez soit utiliser simplement self
comme pour accéder à n'importe quel attribut déclaré dans la classe enfant, ou alors super
, comme pour accéder à une méthode.
Attention, cet article n'est qu'un aperçu de la Programmation Orientée Objet. Il y a beaucoup d'autres choses à savoir, comme les notions d'encapsulation, d'héritage multiple ou de polymorphisme, cependant il constitue une bonne base pour débuter et réaliser des codes simples. Nous verrons plus tard les autres notions évoquées.
Si cet article vous a plus, n'hésitez pas à laisser un commentaire ! Si vous souhaitez vous exprimer ou demander des précisions, vous pouvez me contacter par mail : contact@propython.fr, ou laisser un message via l'onglet Contact visible si vous êtes sur ordinateur.
A très bientôt pour la suite de votre apprentissage du Python !