Python Language Définition de la métaclasse ABCMeta


Exemple

Les classes abstraites sont des classes destinées à être héritées mais évitent d'implémenter des méthodes spécifiques, ne laissant que les signatures de méthode que les sous-classes doivent implémenter.

Les classes abstraites sont utiles pour définir et appliquer des abstractions de classe à un niveau élevé, similaire au concept d'interfaces dans des langages typés, sans qu'il soit nécessaire d'implémenter une méthode.

Une approche conceptuelle pour définir une classe abstraite consiste à extraire les méthodes de classe, puis à générer une erreur NotImplementedError si on y accède. Cela empêche les classes enfants d'accéder aux méthodes parentes sans les remplacer en premier. Ainsi:

class Fruit:
    
    def check_ripeness(self):
        raise NotImplementedError("check_ripeness method not implemented!")


class Apple(Fruit):
    pass


a = Apple()
a.check_ripeness() # raises NotImplementedError

La création d'une classe abstraite de cette manière empêche l'utilisation inappropriée de méthodes qui ne sont pas remplacées, et encourage certainement les méthodes à définir dans les classes enfants, mais elle n'applique pas leur définition. Avec le module abc nous pouvons empêcher les classes enfants d'être instanciées lorsqu'elles ne remplacent pas les méthodes de classes abstraites de leurs parents et ancêtres:

from abc import ABCMeta

class AbstractClass(object):
    # the metaclass attribute must always be set as a class variable 
    __metaclass__ = ABCMeta

   # the abstractmethod decorator registers this method as undefined
   @abstractmethod 
   def virtual_method_subclasses_must_define(self):
       # Can be left completely blank, or a base implementation can be provided
       # Note that ordinarily a blank interpretation implicitly returns `None`, 
       # but by registering, this behaviour is no longer enforced.

Il est maintenant possible de simplement sous-classer et remplacer:

class Subclass(AbstractClass):
    def virtual_method_subclasses_must_define(self):
        return