web-dev-qa-db-fra.com

Forcer la classe enfant à remplacer les méthodes du parent

Supposons que j'ai une classe de base avec des méthodes non implémentées comme suit:

class Polygon():
    def __init__(self):
        pass

    def perimeter(self):
        pass

    def area(self):
        pass

Supposons maintenant qu'un de mes collègues utilise la classe Polygon pour créer une sous-classe comme suit:

import math

class Circle(Polygon):
    def __init__(self, radius):
        self.radius = radius

    def perimeter(self):
        return 2 * math.pi * self.radius

(H/Sh) e a oublié d'implémenter la méthode area ().

Comment puis-je forcer la sous-classe à implémenter la méthode area () du parent?

32
Aditya Barve

cela pourrait être votre classe parente:

class Polygon():
    def __init__(self):
        raise NotImplementedError

    def perimeter(self):
        raise NotImplementedError

    def area(self):
        raise NotImplementedError

bien que le problème ne soit détecté qu'au moment de l'exécution, lorsqu'une des instances des classes enfant tente d'appeler l'une de ces méthodes.


une version différente doit utiliser abc.abstractmethod .

from abc import ABCMeta, abstractmethod
# simpler alternative: from abc import ABC, abstractmethod
import math

class Polygon(metaclass=ABCMeta):
# simpler alternative: class Polygon(ABC)

    @abstractmethod
    def __init__(self):
        pass

    @abstractmethod
    def perimeter(self):
        pass

    @abstractmethod
    def area(self):
        pass

class Circle(Polygon):
    def __init__(self, radius):
        self.radius = radius

    def perimeter(self):
        return 2 * math.pi * self.radius

#    def area(self):
#        return math.pi * self.radius**2


c = Circle(9.0)
# TypeError: Can't instantiate abstract class Circle
#            with abstract methods area

vous ne pourrez pas instancier un Circle sans que toutes les méthodes soient implémentées.

c'est la syntaxe python 3; dans python 2 vous auriez besoin de

class Polygon(object):
    __metaclass__ = ABCMeta

notez également que pour les fonctions spéciales binaires __eq__(), __lt__(), __add__(), ..., il est préférable de return NotImplemented au lieu de relever NotImplementedError.

63
hiro protagonist

C'est exactement à quoi servent NotImplementedError :)

Dans votre classe de base

def area(self):
    raise NotImplementedError("Hey, Don't forget to implement the area!")

Vous pouvez lever NotImplementedError exception dans la méthode de la classe de base.

class Polygon:
    def area(self):
        raise NotImplementedError

Aussi, vous pouvez utiliser @abc.abstractmethod , mais vous devez ensuite déclarer la métaclasse comme abc.ABCMeta , ce qui rendrait votre classe abstraite. En savoir plus sur abc module

4
vishes_shell