Notes et transcriptions du cours “Apprenez la programmation orientée objet avec Python” disponible sur la plateforme Openclassrooms.
La surcharge désigne le concept selon lequel une classe enfant crée une nouvelle implémentation d’une méthode héritée. Lorsqu’une méthode dans une classe enfant est créée avec le même nom et la même signature qu’une méthode dans le parent, la méthode enfant l’emporte.
watch()
, add(a, b)
, ou encore send(message)
sont toutes des signatures de méthode.
En réalité, nous avons utilisé le concept de surcharge une fois ou deux dans les deux chapitres précédents, par exemple avec le ContactSystem
:
Chaque enfant implémente sa propre méthode send(message)
, qui se comporte différemment – elle envoie un SMS, un e-mail, ou un document à l’imprimante.
Et on peut faire cela simplement en écrivant une autre méthode dans la classe enfant ?
C’est aussi simple que ça ! Prenons cet exemple :
from abc import ABC # permet de définir des classes de base class Shape(ABC): def area(self): return 0 class Square(Shape): def __init__(self, length): self.length = length def area(self): return length * length
Dans cet exemple, Shape
(“Forme”) contient une méthode de superficie qui renvoie une aire nulle pour la forme. Square
(“Carré”) surcharge cette méthode en implémentant la formule pour l’aire d’un carré.
Bon, je comprends que area()
est surchargé, mais qu’est-ce que c’est que cet ABC
?
ABC signifie « Abstract Base Class », ou « classe de base abstraite ». Il s’agit du mécanisme utilisé par Python pour implémenter ce que l’on nomme une classe abstraite.
Une classe abstraite est une classe qui ne peut pas être instanciée – la seule façon de l’utiliser est de créer une sous-classe. Par exemple, prenons le cas de Shape
(“Forme”) – qu’est-ce que cela voudrait dire d’avoir un objet Shape
? À quoi est-ce qu’il pourrait bien ressembler ? Nous pourrions faire de Square
, ou Carré, une sous-classe de Shape, puis utiliser notre Carré. Cette approche nous permettrait d’avoir une classe parent commune pour Cercle, Carré, Triangle, etc., sans laisser personne instancier une Shape
.
@abstractmethod
dans la documentation Python.
Bien que la surcharge nous permette de modifier entièrement des comportements hérités, il peut parfois être utile d’avoir accès au code des méthodes des classes parents, depuis les classes enfants.
L’un des emplacements les plus courants pour cette utilisation se trouve dans les constructeurs. Pour cela, nous utilisons super()
– comme ceci :
class Drink: """Une boisson.""" def __init__(self, price): """Initialise un prix.""" self.price = price def drink(self): """Boire la boisson.""" print("Je ne sais pas ce que c'est, mais je le bois.") class Coffee(Drink): """Café.""" prices = {"simple": 1, "serré": 1, "allongé": 1.5} def __init__(self, type): """Initialise le type du café.""" self.type = type super().__init__(price=self.prices.get(type, 1)) def drink(self): """Boire le café.""" print("Un bon café pour me réveiller !")
Dans cet exemple, Coffee
(“café”) est une sous-classe de Drink
(“boisson”). La classe Coffee
possède ses propres tarifs, qu’elle passe au constructeur de Drink
pour initialiser le bon prix !
Est-ce qu’on ne pourrait pas plutôt simplement paramétrer self.price=self.prices.get(type, 1)
dans le constructeur de Coffee
?
Oui, on pourrait, mais cette solution ne peut pas être mise à l’échelle. Imaginez que le constructeur de Drink
applique d’autres opérations au prix (par exemple, appliquer une remise au comptoir), ou que CoffeE
soit encore davantage sous-classé.
L’approche avec super()
vous permet de réutiliser le code plutôt que de le copier, et assure le regroupement des fonctionnalités de façon logique – soit deux des plus grands avantages de la programmation orientée objet !
Finissons sur nos films : notre film en cassette ne rentre pas dans le lecteur DVD du salon… 🤔 Peut-être qu’avec la surcharge, nous pouvons proposer une vérification du lecteur (avant de casser le lecteur DVD !) :
Dans cet exercice, nous allons ajouter de la surcharge au code que nous avons utilisé au chapitre précédent.
Mais tout d’abord, voyez-vous des classes dans votre hiérarchie qui devraient être abstraites ? Si oui, transformez-les en classes abstraites.
Surchargez la méthode d’affichage de FilePost
(ou de votre équivalent) pour afficher son fichier ( File
) correspondant en haut du post. Puis, surchargez la méthode d’affichage de votre classe Image
pour écrire dans la sortie standard le nom de l’image.
Dans le chapitre suivant, nous nous pencherons sur différentes façons d’utiliser l’héritage : les hiérarchies d’héritage et l’héritage multiple.