静态方法和继承设计

时间:2016-06-06 14:09:54

标签: python inheritance polymorphism static-methods

我不清楚使用可以覆盖的静态方法设计类的最佳方法是什么。我将尝试用一个例子来解释。

我们有一个类Goat,其方法为can_climb。 (顺便说一下,这是Python 3,在Python 2中我会写class Goat(object):。)

class Goat:
    def __init__(self, *args):
        ...

    def can_climb(self, mountain):
        return mountain.steepness < 10

billy = Goat("Billy")
if billy.can_climb(mount_everest):
    print("wow Billy, impressive")

这可以按预期工作,但方法can_climb不使用self。使它成为静态方法看起来更干净,而且pylint甚至会对上述方法发出警告。所以让我们改变一下:

class Goat:
    def __init__(self, *args):
        ...

    @staticmethod
    def can_climb(mountain):
        return mountain.steepness < 10

billy = Goat("Billy")
if billy.can_climb(mount_everest):
    print("wow Billy, impressive")
最后的

billy.can_climb可以改为Goat.can_climb,在这个例子中它不会有所作为。有些人甚至可能会认为通过类而不是实例调用静态方法更清晰,更直接。

但是,当我们使用继承并引入多态时,这会导致一个微妙的错误:

class Goat:
    def __init__(self, *args):
        ...

    @staticmethod
    def can_climb(mountain):
        return mountain.steepness < 10

class MountaineeringGoat(Goat):
    @staticmethod
    def can_climb(mountain):
        return True

billy = get_ourselves_a_goat_called_billy()
if Goat.can_climb(mount_everest):     # bug
    print("wow Billy, impressive")

调用Goat.can_climb的代码知道billyGoat的一个实例,并且当它确实是任何子类型时,会错误地假设其类型为Goat Goat。或者它可能错误地假定子类不会覆盖静态方法。

在我看来,这似乎是一个容易犯的错误;也许Goat在引入这个bug的时候没有任何子类,所以没有注意到这个bug。

我们如何设计和记录课程以避免这种错误?特别是,此示例中的can_climb应该是静态方法还是应该使用其他方法?

1 个答案:

答案 0 :(得分:9)

继承显然意味着对基类的了解。 @staticmethod不知道它所附带的课程是什么? to(因此他们早些时候 - 不是现在 - 称为它&#39;未绑定;&#39;现在技术上@staticmethod根本不是一种方法;它是一种功能。

@classmethod完全了解它附加的类;它在技术上不是一种功能,而是一种方法。

为什么然后@staticmethod呢?它在派生类中继承,但如前所述,不知道基类;我们可以使用它这样的&#39;好像我们已在派生类中定义它。

非技术性@classmethod s 'bounded';@staticmethod不是。

如果有人问我,我会为@staticfunction建议名称@staticmethod