python n'avait pas de classe ou d'interface abstraite. Cependant, avec l'ajout du module abc (abréviation de la classe de base abstraite), il est devenu possible d'y parvenir en utilisant des décorateurs. Cette fois, expérimentons pour découvrir les conditions dans lesquelles la classe abstraite donne réellement une erreur.
Les classes abstraites appliquent les fonctions (méthodes) que vous souhaitez qu'elles implémentent. Si vous ne l'implémentez pas en python, vous n'obtiendrez une erreur que lorsque vous instanciez une classe implémentée (plus précisément, une classe non implémentée). Par conséquent, même une classe qui n'implémente pas de méthode abstraite ne provoquera pas d'erreur si elle est uniquement accessible pour utiliser la méthode de classe. Dans les cas suivants, l'erreur se produit uniquement lors de l'instanciation de la classe abstraite et de ses sous-classes.
from abc import *
class Abstract(object, metaclass=ABCMeta):
@classmethod
@abstractmethod
def hello(cls):
print("Abstract hello")
class Implement(Abstract):
pass
Abstract.hello()
# => Abstract hello
Implement.hello()
# => Abstract hello
# Abstract()
# TypeError: Can't instantiate abstract class Abstract with abstract methods hello
# Implement()
# TypeError: Can't instantiate abstract class Implement with abstract methods hello
Bien sûr, lors de l'instanciation, vous devez implémenter (définir) une méthode abstraite. Même si vous créez une autre méthode, elle n'est pas reconnue comme implémentée. En d'autres termes, il ne répond pas aux critères du créateur de la classe abstraite. Vérifions-le.
from abc import *
class Abstract(object, metaclass=ABCMeta):
@classmethod
@abstractmethod
def hello(cls):
print("Abstract hello")
class Implement(Abstract):
@classmethod
def say(cls):
print("Implement class-method say")
def yeah(self):
print("Implement instance-method yeah")
Implement()
# => TypeError: Can't instantiate abstract class Implement with abstract methods hello
Définissez une méthode de classe d'une classe abstraite en tant que méthode abstraite. Si vous définissez une méthode portant le même nom qu'une méthode d'instance dans cette sous-classe, aucune erreur ne se produira. Peut-être que python est tous des objets et indiscernable, donc il ne détermine que le nom, pas le type de méthode.
from abc import *
class Abstract(object, metaclass=ABCMeta):
@classmethod
@abstractmethod
def hello(cls):
print("Abstract hello")
class Implement(Abstract):
def hello(self):
print("Implement hello")
impl = Implement()
impl.hello()
# => Implement hello
Définissons une méthode de classe abstraite comme méthode d'instance et une méthode d'instance abstraite comme méthode de classe. L'erreur cette fois est due à l'absence de la méthode de classe bonjour. Étant donné que la sous-classe hello est une instance et que la classe parente hello est une méthode abstraite, la méthode de classe entraînera une erreur car hello n'est pas implémentée. Cela ne cause pas d'erreur pour accéder à la classe, mais cela dit que c'est inutile car il n'y a aucune méthode pour l'utiliser.
from abc import *
class Abstract(object, metaclass=ABCMeta):
@classmethod
@abstractmethod
def hello(cls):
print("Abstract hello")
def say(self):
print("Abstract say")
class Implement(Abstract):
def hello(self):
print("Implement hello")
@classmethod
def say(cls):
print("Implement say")
impl = Implement()
impl.hello()
impl.say()
# =>
# Implement hello
# Implement say
# Implement.hello()
# hello() missing 1 required positional argument: 'self'
Implement.say()
# =>
# Implement say
Dans cette expérience, nous avons constaté qu'il n'est pas possible de faire la distinction entre les méthodes de classe et les méthodes d'instance. Vous avez peut-être préparé l'erreur vous-même ou vous avez peut-être une méthode dans les options du module abc. Mais gardez à l'esprit que l'utilisation normale ne peut que limiter l'implémentation de méthodes portant le même nom.
Recommended Posts