La POO est un paradigme de programmation qui organise le code autour d’objets plutôt que de fonctions et de procédures.
Ces objets représentent des entités du monde réel, ils ont :
La POO permet :
Elle est largement utilisée dans de nombreux langages de programmation, dont Python, pour développer des applications complexes et évolutives.
Modélisons par exemple une personne :
Les méthodes peuvent agir sur les attributs
La méthode vieillir() va augmenter l’age de la personne de 1.
La méthode apprendre(“Python”), va ajouter “Python” à la liste des compétences.
L’encapsulation consiste à regrouper les données et les méthodes qui les manipulent au sein d’un même objet.
Cela permet de :
L’héritage permet de créer de nouvelles classes à partir de classes existantes, en héritant de leurs attributs et méthodes. Cela favorise :
Exemple : Carré hérite de Rectangle. Un carré est un rectangle avec des propriétés supplémentaires.
Le polymorphisme permet à des objets de classes différentes de répondre de manière différente à une même action.
Cela permet de manipuler des objets de différentes classes de manière uniforme, en utilisant des interfaces communes.
personne.py
class Personne:
def __init__(self, nom, prenom, age):
self.nom = nom
self.prenom = prenom
self.age = age
self.competences = []
def apprendre(self, nouvelle_competence):
"""Ajoute une nouvelle compétence à la liste des compétences."""
self.competences.append(nouvelle_competence)
def vieillir(self):
"""Incrémente l'âge de la personne d'un an."""
self.age += 1
À partir de la classe Personne, nous pouvons créer des objets.
Le code Personne("Touille", "Sacha", 20)
appelle la méthode __init__()
de la classe Personne.
Cette méthode est appelée le constructeur.
Comme son nom l’indique, elle permet de « construire » des objets à partir de la classe.
_
)Un des trois piliers de la POO est l’héritage.
Une classe enfant peut utiliser tous les attributs et méthodes de sa classe mère.
Ce principe d’héritage permet également de mettre en commun des attributs et méthodes pour éviter des duplications de code.
Supposons que dans notre code, nous voulons gérer des vélos et de trottinettes.
L’idée naïve est de créer une classe pour chacun.
velo.py
class Velo:
def __init__(self, couleur, nb_pignons):
self.couleur = couleur
self.nb_pignons = nb_pignons
self.vitesse = 0 # La vitesse initiale est 0
def accelerer(self, increment):
"""Augmente la vitesse du vélo."""
self.vitesse += increment
def ralentir(self, decrement):
"""Diminue la vitesse du vélo."""
self.vitesse -= decrement
if self.vitesse < 0:
self.vitesse = 0 # La vitesse ne peut pas être négative
trottinette.py
class Trottinette:
def __init__(self, couleur, nb_pignons):
self.couleur = couleur
self.vitesse = 0 # La vitesse initiale est 0
def accelerer(self, increment):
"""Augmente la vitesse."""
self.vitesse += increment
def ralentir(self, decrement):
"""Diminue la vitesse."""
self.vitesse -= decrement
if self.vitesse < 0:
self.vitesse = 0 # La vitesse ne peut pas être négative
En réfléchissant un peu, nous nous disons que ces 2 classes ont des attributs et méthodes en commun :
Une idée est de regrouper ces caractéristiques communes dans une classe DeuxRoues
. Puis de faire hériter Vélo
et Trottinette
de DeuxRoues
deux_roues.py
class DeuxRoues:
def __init__(self, couleur):
self.couleur = couleur
self.vitesse = 0 # La vitesse initiale est 0
def accelerer(self, increment):
"""Augmente la vitesse."""
self.vitesse += increment
def ralentir(self, decrement):
"""Diminue la vitesse."""
self.vitesse -= decrement
if self.vitesse < 0:
self.vitesse = 0 # La vitesse ne peut pas être négative
Dessine-moi un deux roues
Si l’on vous demande de dessiner un deux-roues, vous ne savez pas vraiment comment faire, vous manquez d’informations.
Alors que dessiner un vélo ou une trottinette, c’est déjà plus concret.
Certaines classes n’ont pas vocation à être instanciées. Par exemple, nous n’allons pas créer d’objets de la classe DeuxRoues.
Nous allons directement créer des Velo et des Trottinettes.
Nous pouvons donc définir la classe DeuxRoues comme abstraite.
La principale utilité des classes abstraites est de définir un contrat pour les classes filles.
Elles fournissent une structure et une organisation cohérentes pour les classes qui partagent des caractéristiques communes, tout en permettant une flexibilité pour les implémentations spécifiques à chaque classe fille.
Tip
En Python, la notion de classe abstraite est implémentée grâce au module abc (Abstract Base Classes).
Ce module fournit le décorateur @abstractmethod
qui permet de déclarer une méthode comme abstraite dans une classe abstraite.
Une classe abstraite est définie en héritant de la classe ABC du module abc.
Warning
Classe mère ne veut pas dire forcément classe abstraite.
Par exemple :
VeloElectrique
qui hérite de la classe Velo
Velo
n’a pas vocation à être abstraite car il n’est pas absurde de créer un objet vélo