Classes et méthodes abstraites
Fait partie de la section Object Oriented Programming du Journey Python de Coddy — leçon 25 sur 64.
Les classes abstraites sont des classes qui ne peuvent pas être instanciées directement et contiennent des méthodes abstraites qui doivent être implémentées par des sous-classes.
Considérez cela comme un formulaire : Une classe abstraite est comme un code de formulaire obligatoire où certains champs sont requis (méthodes abstraites) et d'autres sont facultatifs (méthodes concrètes). Vous ne pouvez pas soumettre le formulaire lui-même - vous devez d'abord remplir tous les champs obligatoires. De même, vous ne pouvez pas créer d'instances d'une classe abstraite tant que toutes les méthodes abstraites n'ont pas été implémentées dans une sous-classe.
Importez le module abc pour créer des classes abstraites :
from abc import ABC, abstractmethodCréez une classe abstraite avec des méthodes abstraites :
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # Méthode concrète (a une implémentation)Le décorateur @abstractmethod marque les méthodes qui doivent être implémentées par les sous-classes - ce sont les « champs obligatoires » de votre formulaire. Les méthodes régulières comme describe() peuvent avoir des implémentations et sont héritées telles quelles - ce sont les « champs pré-remplis ».
Pourquoi utiliser des classes abstraites ? Elles imposent un contrat. Si vous créez une classe Shape, vous dites que « chaque forme DOIT être capable de calculer son aire et son périmètre ». Cela évite les bugs où vous pourriez oublier d'implémenter des méthodes critiques.
Essayez de créer une instance de la classe abstraite :
# Cela provoquera une erreur :
# shape = Shape() # TypeError: Can't instantiate abstract classCette erreur est intentionnelle - c'est comme essayer de soumettre un formulaire vide. Python dit : « Vous n'avez pas encore rempli les champs obligatoires (méthodes area et perimeter) ! »
Créez une sous-classe concrète qui implémente toutes les méthodes abstraites :
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radiusMaintenant, nous avons « rempli tous les champs obligatoires » - nous avons implémenté à la fois area() et perimeter(). La classe Circle est désormais une classe concrète complète qui peut être instanciée.
Vous pouvez maintenant créer des instances de la classe concrète :
circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe()) # Méthode concrète héritéeCréez une autre sous-classe concrète :
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width self.height
def perimeter(self):
return 2 * (self.width + self.height)
rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())Sortie :
78.5
31.400000000000002
This is a shape
24
20Les classes abstraites définissent un contrat que les sous-classes doivent suivre. Utilisez ABC et @abstractmethod pour créer des classes abstraites. Les sous-classes doivent implémenter toutes les méthodes abstraites, sinon elles seront également abstraites. Cela garantit la cohérence et empêche les implémentations incomplètes.
Défi
MoyenDans ce défi, vous allez implémenter un système de traitement des paiements.
Vous devez compléter l'implémentation dans ces fichiers :
paymentmethod.py- Classe de base abstraite avec une logique de validationcreditcard.py- Implémentation du paiement par carte de créditpaypal.py- Implémentation du paiement PayPal
Suivez les commentaires TODO dans chaque fichier pour implémenter la fonctionnalité requise. Les commentaires vous guideront étape par étape dans la création de méthodes abstraites, l'implémentation de sous-classes concrètes et l'établissement de relations d'importation appropriées entre les fichiers.
Le fichier driver.py contient des cas de test qui vérifieront que votre implémentation fonctionne correctement, en traitant différents scénarios de paiement et en affichant les détails appropriés pour chaque méthode de paiement.
Aide-mémoire
Les classes abstraites ne peuvent pas être instanciées directement et contiennent des méthodes abstraites qui doivent être implémentées par les sous-classes.
Importez le module abc :
from abc import ABC, abstractmethodCréez une classe abstraite avec des méthodes abstraites :
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
def describe(self):
return "This is a shape" # Méthode concrète (a une implémentation)Le décorateur @abstractmethod marque les méthodes qui doivent être implémentées par les sous-classes. Les méthodes régulières peuvent avoir des implémentations.
Les classes abstraites ne peuvent pas être instanciées :
# Cela provoquera une erreur :
# shape = Shape() # TypeError: Can't instantiate abstract classCréez des sous-classes concrètes qui implémentent toutes les méthodes abstraites :
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
circle = Circle(5)
print(circle.area()) # 78.5
print(circle.describe()) # Méthode concrète héritéePoint clé : Les classes abstraites définissent un modèle que les sous-classes doivent suivre. Les sous-classes doivent implémenter toutes les méthodes abstraites, sinon elles seront également abstraites.
Essayez vous-même
from creditcard import CreditCard
from paypal import PayPal
# Tester les implémentations - NE PAS MODIFIER CE CODE DE TEST
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")
# Traiter les paiements valides
if cc.validate(100):
print(cc.process_payment(100))
print(cc.payment_details())
if pp.validate(200):
print(pp.process_payment(200))
print(pp.payment_details())
# Essayer un montant invalide
if not pp.validate(0):
print("Invalid payment amount")
# Cela générerait une erreur si décommenté :
# pm = PaymentMethod() # Impossible d'instancier une classe abstraiteCette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Object Oriented Programming
1Les fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe paramètre selfMéthodesAttributsMéthode constructeur (__init__)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLa fonction super()Redéfinition de méthodeHéritage multipleOrdre de résolution des méthodesRécapitulatif - Hiérarchie des employés7Méthodes spéciales
Introduction aux méthodes magiquesSurcharge d'opérateursMéthodes magiques de conteneurRécapitulatif - Liste personnalisée10Patrons de conception, Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron Strategy2Décorateurs
Introduction aux décorateursDécorateur de propriétéDécorateur de méthode statiqueDécorateur de méthode de classe5Polymorphisme
Retour sur la redéfinition de méthodeDuck TypingClasses et méthodes abstraitesConception d'interfacesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageMixinsMéthodes statiques et de classeDécorateurs de classeGestionnaires de contexte11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Propriétés de classe
Variables d'instance vs variables de classeDécorateurs de propriétéAttributs privésRécapitulatif - Gestionnaire de compte bancaire