La Programmation Orientée Objet (POO) est un paradigme de programmation qui utilise des "objets" pour représenter des données et des méthodes.
Un objet est une instance d'une classe, qui peut être considérée comme un modèle ou un plan définissant les attributs et les comportements de l'objet.
Les classes
Une classe est une structure qui définit les attributs et les méthodes que ses objets peuvent posséder. Elle sert de plan pour créer des objets.
class Voiture:
def __init__(self, marque, modèle):
self.marque = marque
self.modèle = modèle
def démarrer(self):
print(f"{self.marque} {self.modèle} démarre.")
# Exemple de classe 'Voiture' avec des attributs et une méthode
Les objets
Un objet est une instance d'une classe. Il contient des données et des méthodes définies par la classe.
ma_voiture = Voiture("Mazda", "RX7")
ma_voiture.démarrer() # Sortie: Mazda RX7 démarre.
# 'ma_voiture' est un objet de la classe 'Voiture'
Les attributs
En Python, les attributs d’un objet englobent à la fois les variables (qu'on peut aussi retrouver sous le nom de propriétés) et les méthodes (les fonctions définies au sein de la classe).
En d’autres termes, tout ce qui est associé à une instance d’une classe (ou à la classe elle-même si on parle d’attributs de classe) est considéré comme un attribut.
class Produit: # Attribut de classe nombre_de_produits = 0 def __init__(self, nom, prix): # Attributs d'instance self.nom = nom self.prix = prix # Incrémenter le compteur d'attribut de classe à chaque création d'instance Produit.nombre_de_produits += 1 def affiche_produit(self): print(f"{self.nom} : coûte {self.prix}") # Création de quelques instances de Produit produit1 = Produit("Ordinateur", 1000) produit2 = Produit("Smartphone", 500) produit3 = Produit("Tablette", 300) # Accès à l'attribut de classe print(f"Nombre total de produits créés: {Produit.nombre_de_produits}")
Pour afficher tous les attributs d'un objet, on peut utiliser la fonction dir
:
class Produit: # Attribut de classe nombre_de_produits = 0 def __init__(self, nom, prix): # Attributs d'instance self.nom = nom self.prix = prix # Incrémenter le compteur d'attribut de classe à chaque création d'instance Produit.nombre_de_produits += 1 def affiche_produit(self): print(f"{self.nom} : coûte {self.prix}") produit1 = Produit("Ordinateur", 1000) print(dir(produit1))
Le code ci-dessus affiche à la fois les variables définies dans la méthode __init__
(nom
et prix
) mais également l'attribut d'instance nombre_de_produits
et le nom des méthodes définies dans la classe (__init__
et affiche_produit
).
Vous remarquerez également plein d'autres noms d'attributs qui n'apparaissent pas dans notre code (__sizeof__
, __new__
, etc). Il s'agit de méthodes spéciales, identifiées par les doubles underscore qui les entourent.
Il s'agit en effet de toutes les méthodes de bases définies dans la classe object
, dont toutes les classes héritent par défaut.
Le code :
class Produit:
est en effet similaire à :
class Produit(object):
Depuis Python 3, il n'est plus nécessaire d'indiquer cet héritage implicite et on peut juste déclarer notre classe par son nom.
Les méthodes
Les méthodes sont des fonctions définies à l'intérieur d'une classe. Elles décrivent les comportements des objets de cette classe.
class Personne:
def __init__(self, nom, âge):
self.nom = nom
self.âge = âge
def se_présenter(self):
print(f"Bonjour, je m'appelle {self.nom} et j'ai {self.âge} ans.")
personne = Personne("Kévin", 20)
personne.se_présenter() # Sortie: Bonjour, je m'appelle Kévin et j'ai 20 ans.
# 'se_présenter' est une méthode de la classe 'Personne'
L'encapsulation
L'encapsulation est le principe de restreindre l'accès direct à certaines données d'un objet et de contrôler cet accès via des méthodes. Cela protège les données internes de l'objet contre les modifications non autorisées. Pour cela, on utilise un underscore _
devant le nom de l'attribut.
class CompteBancaire:
def __init__(self, solde):
self._solde = solde # Attribut privé
def déposer(self, montant):
self._solde += montant
def retirer(self, montant):
if montant <= self.__solde:
self._solde -= montant
else:
print("Fonds insuffisants")
def afficher_solde(self):
print(f"Solde: {self._solde}")
compte = CompteBancaire(100)
compte.déposer(50)
compte.retirer(30)
compte.afficher_solde() # Sortie: Solde: 120
# '_solde' est un attribut privé accessible uniquement via les méthodes de la classe
Héritage
L'héritage permet à une classe de dériver d'une autre classe, en héritant de ses attributs et méthodes. Cela favorise la réutilisation du code et la création de hiérarchies de classes.
class Animal:
def __init__(self, nom):
self.nom = nom
def parler(self):
pass
class Chien(Animal):
def parler(self):
print("Woof!")
class Chat(Animal):
def parler(self):
print("Miaou!")
chien = Chien("Rex")
chat = Chat("Tigrou")
chien.parler() # Sortie: Woof!
chat.parler() # Sortie: Miou!
# 'Chien' et 'Chat' héritent de la classe 'Animal'
Polymorphisme
Le polymorphisme permet à des objets de classes différentes d'être traités comme des objets de la même classe via des interfaces communes.
Cela permet d'utiliser des méthodes dans une interface commune sans connaître les détails des classes spécifiques.
class Oiseau:
def parler(self):
print("Cui-Cui!")
def faire_parler(animal):
animal.parler()
faire_parler(Chien("Rex")) # Sortie: Woof!
faire_parler(Chat("Tigrou")) # Sortie: Miaou!
faire_parler(Oiseau()) # Sortie: Cui-Cui!
# Le polymorphisme permet d'utiliser une méthode commune 'parler' sur différents types d'animaux
Abstraction
L'abstraction consiste à créer des classes abstraites qui définissent des méthodes communes sans implémenter leur logique. Ce sont les classes dérivées qui implémentent ces méthodes.
from abc import ABC, abstractmethod
class Forme(ABC):
@abstractmethod
def aire(self):
pass
class Rectangle(Forme):
def __init__(self, largeur, hauteur):
self.largeur = largeur
self.hauteur = hauteur
def aire(self):
return self.largeur * self.hauteur
rectangle = Rectangle(5, 3)
print(rectangle.aire()) # Sortie: 15
# 'Forme' est une classe abstraite avec une méthode abstraite 'aire' implémentée par 'Rectangle'
À quoi ça sert la POO ?
-
Réutilisation du code : Grâce à l'héritage, le code peut être réutilisé, ce qui réduit la duplication et facilite la maintenance.
-
Modularité : La POO permet de diviser un programme en morceaux indépendants (classes et objets), rendant le code plus facile à comprendre et à maintenir.
-
Extensibilité : Les programmes orientés objet sont plus faciles à étendre. De nouvelles fonctionnalités peuvent être ajoutées en créant de nouvelles classes ou en modifiant les classes existantes sans affecter le reste du programme.
-
Encapsulation : L'encapsulation protège les données et assure une manipulation cohérente et sécurisée des attributs de l'objet.