【问题标题】:Force child class to override parent's methods强制子类覆盖父类的方法
【发布时间】:2017-11-18 11:01:00
【问题描述】:

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

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

    def perimeter(self):
        pass

    def area(self):
        pass

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

import math

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

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

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

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

【问题讨论】:

    标签: python inheritance overriding


    【解决方案1】:

    这可能是你的父类:

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

    虽然问题只会在运行时被发现,但当子类的实例之一尝试调用这些方法之一时。


    另一个版本是使用abc.abstractmethod。

    from abc import ABC, abstractmethod
    import math
    
    
    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
    

    如果没有实现所有方法,您将无法实例化 Circle。

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

    class Polygon(object):
        __metaclass__ = ABCMeta
    

    还要注意,对于二进制特殊函数__eq__(), __lt__(), __add__(), ...,最好使用return NotImplemented 而不是提高NotImplementedError。

    【讨论】:

    • 我会将您的第二个选项作为主要选项,让第一个选项成为有缺点的替代选项。遵循 python 的禅宗,我只会保留你的第二个选项的简单版本,因为它更简单并且工作得很好。
    【解决方案2】:

    这正是NotImplementedError 的用途:)

    在你的基类中

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

    【讨论】:

    • 这仅在您尝试调用area() 方法时有效。如果要真正强制用户实现所有方法,则需要 ABC 模块。
    【解决方案3】:

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

    class Polygon:
        def area(self):
            raise NotImplementedError
    

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

    【讨论】:

      猜你喜欢
      • 2018-03-18
      • 2011-05-21
      • 1970-01-01
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多