Module 2Connaître les principaux piliers de la POO
Chapitre 4 sur 10
Connaître l'encapsulation
Protéger l'état des objets grâce aux niveaux de visibilité et aux accesseurs.
- ≈ 110 min
- 4 leçons
- 2 exercices
- TP
Module 2Connaître les principaux piliers de la POO
Chapitre 4 sur 10
Protéger l'état des objets grâce aux niveaux de visibilité et aux accesseurs.
Objectifs
Avec ce chapitre, tu sauras…
_attribut, __attribut, accesseurs et @property.Leçon 1
┌─────────────────────────────┐
│ Interface (publique) │ ◀── ce que les autres objets voient
│ retirer() deposer() │
│ ┌─────────────────────────┐ │
│ │ Partie privée │ │ ◀── caché
│ │ numero_compte, solde │ │
│ └─────────────────────────┘ │
└─────────────────────────────┘Leçon 2
Les attributs de la classe Compte (numéro, solde) sont privés. Un client ne peut modifier son solde qu'à travers les méthodes publiques deposer() et retirer(). Ces méthodes peuvent contrôler chaque opération : refuser un retrait supérieur au solde, refuser un montant négatif.
| Sans encapsulation | Avec encapsulation |
|---|---|
compte.solde = -50000 : n'importe quel code peut mettre le solde à n'importe quelle valeur | compte.retirer(50000) : la méthode vérifie et refuse |
| une modification de la structure interne casse tout le code qui l'utilisait | on peut changer l'implémentation interne sans toucher à l'interface |
Leçon 3
| Niveau | Qui peut accéder ? | Protection |
|---|---|---|
| public | les méthodes de toutes les classes | la plus faible |
| privé | uniquement les méthodes de la classe elle-même | la plus forte |
| Mécanisme | Principe | Exemple de langage |
|---|---|---|
Leçon 4
| Écriture | Sens | Accès depuis l'extérieur |
|---|---|---|
self.solde | public | libre |
self._solde | protégé par convention : « usage interne, ne pas toucher » | possible, mais déconseillé |
self.__solde | privé : Python renomme l'attribut en _Compte__solde (name mangling) | compte.__solde provoque une erreur |
1L'encapsulation consiste à…
2L'interface d'un objet est…
3Un membre privé est accessible…
4Le niveau réservé aux classes dérivées est…
5En Python, un attribut privé s'écrit…
6Un mutateur sert à…
L'essentiel du chapitre
attr public, _attr protégé par convention, __attr privé ; accesseurs/mutateurs et @property.| une classe rend ses membres privés accessibles à quelques classes « amies » qu'elle désigne |
friend en C++ |
| classe dans une classe | une classe interne a accès aux membres privés de la classe qui l'englobe | classes internes Java |
héritage : protégé (protected) | seuls les enfants (classes dérivées) accèdent aux membres protégés | Java, C#, C++, PHP |
| paquetages | l'accès est ouvert aux classes du même paquetage (même répertoire) | visibilité par défaut en Java |
Accesseur et mutateur
Tableau: Les niveaux intermédiaires (résumé OFPPT)
Python n'a pas de mots-clés public / private : il utilise des conventions de nommage.
class Compte:
def __init__(self, numero, solde_initial=0):
self.__numero = numero # privé
self.__solde = solde_initial # privé
def deposer(self, montant): # interface publique
if montant <= 0:
raise ValueError("Le montant doit être positif.")
self.__solde += montant
def retirer(self, montant):
if montant > self.__solde:
raise ValueError("Solde insuffisant.")
self.__solde -= montant
def get_solde(self): # accesseur (getter)
return self.__solde
c = Compte("MA001", 1000)
c.deposer(500)
c.retirer(200)
print(c.get_solde()) # 1300
# print(c.__solde) # AttributeError : l'attribut est privéLes propriétés : la manière pythonique
class Produit:
def __init__(self, nom, prix):
self.nom = nom
self.prix = prix # passe par le mutateur ci-dessous
@property
def prix(self): # accesseur : produit.prix
return self.__prix
@prix.setter
def prix(self, valeur): # mutateur : produit.prix = 99
if valeur < 0:
raise ValueError("Le prix ne peut pas être négatif.")
self.__prix = valeur
p = Produit("Clavier", 250)
p.prix = 199 # contrôlé par le mutateur
print(p.prix) # 199Pourquoi est-il dangereux que l'attribut solde d'un compte soit public ? Donne deux exemples de problèmes, puis explique comment l'encapsulation les évite.
Écris la classe Stagiaire avec des attributs privés __nom et __notes (liste), une méthode ajouter_note(note) qui refuse les notes hors de 0 à 20, une propriété moyenne en lecture seule et une propriété nom avec accesseur et mutateur (le nom ne peut pas être vide).
Par défaut, les attributs sont privés et les méthodes de service sont publiques. On ne rend public que ce qui est nécessaire à l'utilisation de l'objet.
Un accesseur (getter) est une méthode qui lit un attribut privé ; un mutateur (setter) est une méthode qui le modifie en contrôlant la nouvelle valeur. En Python, @property permet de les utiliser avec la syntaxe simple d'un attribut.
Écrire automatiquement un getter et un setter pour chaque attribut revient à tout rendre public. Ne crée un mutateur que si la modification de l'attribut a un sens pour l'utilisateur, et fais-lui vérifier la valeur. Un numéro de compte, par exemple, ne devrait pas avoir de mutateur.