Menu
Coddy logo textTech

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, abstractmethod

Cré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 class

Cette 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.radius

Maintenant, 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ée

Cré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
20

Les 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.

challenge icon

Défi

Moyen

Dans 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 validation
  • creditcard.py - Implémentation du paiement par carte de crédit
  • paypal.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, abstractmethod

Cré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 class

Cré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ée

Point 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 abstraite
quiz iconTestez-vous

Cette 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