抽象类能否强制继承类实现静态方法?

9 投票
1 回答
2632 浏览
提问于 2025-04-17 08:00

这是关于Python 3.2的内容,如果这对你有用的话...

下面的代码展示了“具体类”可以把some_method实现为静态方法或者实例方法:

import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def some_method(self): pass

class ValidConcreteClass1(SomeAbstractClass):

    @staticmethod
    def some_method():
        print("foo!")

class ValidConcreteClass2(SomeAbstractClass):

    def some_method(self):
        print("foo!")

ValidConcreteClass1.some_method()

instance = ValidConcreteClass2()
instance.some_method()

我想问的是,我能不能强制要求继承的类实现some_method为静态方法呢?

我注意到了@abc.abstractstaticmethod,以为这就是答案,但下面的代码还是可以正常运行。我本以为这会拒绝ValidConreteClass2,因为some_method不是静态方法:

import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractstaticmethod
    def some_method(self): pass

class ValidConcreteClass1(SomeAbstractClass):

    @staticmethod
    def some_method():
        print("foo!")

class ValidConcreteClass2(SomeAbstractClass):

    def some_method(self):
        print("foo!")

ValidConcreteClass1.some_method()

instance = ValidConcreteClass2()
instance.some_method()

1 个回答

3

我觉得有必要澄清一下:

首先,在Python中,每个方法都是虚拟的——真的很虚拟;所以一个方法是静态的,还是绑定到类或实例上,这个问题其实是子类的事,而不是父类的事。你没有真正的理由想要阻止这一点——你这么做的目的是什么呢?

其次,抽象基类(ABCs)在实例化时会检查抽象性——如果你尝试实例化一个还有抽象方法的类,就会报错。但是,ABCs对从类本身调用的静态方法或类方法并没有任何检查——方法本身不会被检查,只是在方法上设置了一个属性——是ABCMeta在类被实例化时做了这些检查。

第三,abstractstaticmethod的目的是允许一个抽象方法——也就是说,子类必须以某种方式重写它——可以是静态的,并且可以从任何地方使用——同样,方法本身并没有被检查,所以下面的代码是完全合法的:

import abc

class SomeAbstractClass(metaclass=abc.ABCMeta):

    @abc.abstractstaticmethod
    def some_method(): 
        return 123

class ValidConcreteClass1(SomeAbstractClass):

    def some_method(self):
        return 456

inst = ValidConcreteClass1()
print(inst.some_method())
print(SomeAbstractClass.some_method())

abstractstaticmethod和abstractclassmethod存在的唯一原因是,下面的代码无法工作,因为被装饰的方法缺少一个字典

class NotWorking(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    @staticmethod
    def some_method(self):
        return "asd"

最后一点: 如果你真的想要的话,可能可以通过扩展ABCMeta来添加这样的功能,但除非你告诉我你这么做的原因,否则我不会告诉你怎么做这个 :-)

撰写回答