强制子类覆盖父方法

Adi*_*rve 35 python inheritance overriding

假设我有一个带有未实现方法的基类,如下所示:

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

    def perimeter(self):
        pass

    def area(self):
        pass
Run Code Online (Sandbox Code Playgroud)

现在,假设我的一位同事使用Polygon类创建子类,如下所示:

import math

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

    def perimeter(self):
        return 2 * math.pi * self.radius
Run Code Online (Sandbox Code Playgroud)

(H/Sh)e忘记实现area()方法.

如何强制子类实现父的area()方法?

hir*_*ist 70

这可能是你的父类:

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

    def perimeter(self):
        raise NotImplementedError

    def area(self):
        raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)

虽然问题只会在运行时发现,但是当其中一个子类的实例尝试调用其中一种方法时.


使用不同的版本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
Run Code Online (Sandbox Code Playgroud)

如果没有Circle实现所有方法,你将无法实例化.

这是python 3语法; 在python 2你需要

class Polygon(object):
    __metaclass__ = ABCMeta
Run Code Online (Sandbox Code Playgroud)

另请注意,对于二进制特殊函数 __eq__(), __lt__(), __add__(), ...,最好return NotImplemented不要提高NotImplementedError.


vis*_*ell 6

您可以NotImplementedError在基类方法中引发异常。

class Polygon:
    def area(self):
        raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)

您也可以使用@abc.abstractmethod,但是您需要将元类声明为abc.ABCMeta,这将使您的类成为抽象类。更多关于abc模块


Bub*_*Gut 5

那正是NotImplementedError用于:)

在你的基础班

def area(self):
    raise NotImplementedError("Hey, Don't forget to implement the area!")
Run Code Online (Sandbox Code Playgroud)

  • 这只在您尝试调用“area()”方法时才有效。如果你想真正强制用户实现所有方法,就需要ABC模块。 (2认同)