即使子类重写了我的类的某个方法,我如何确保它始终被调用?

2024-09-30 18:22:28 发布

您现在位置:Python中文网/ 问答频道 /正文

例如,我有一个

class BaseHandler(object):
    def prepare(self):
        self.prepped = 1

我不希望每个子类BaseHandler并希望实现prepare的人都必须记住调用

super(SubBaseHandler, self).prepare()

即使子类也实现了prepare,是否有办法确保超类方法运行


Tags: 方法selfobjectdefprepare子类classsuper
3条回答

只需接受这样一个事实,即在重写基类时,您必须告诉类的子类化人员调用基类方法。其他任何解决方案要么需要你解释他们做其他事情,要么涉及一些非pythonic的黑客,这些黑客也可以规避

Python的对象继承模型被设计为开放的,任何尝试另一种方式都只会使问题过于复杂,而这个问题实际上并不存在。只要告诉所有使用你的东西的人要么遵守你的“规则”,否则程序就会一团糟

我已经用元类解决了这个问题

使用元类允许BaseHandler的实现者确保所有子类都将调用超类prepare(),而不需要调整任何现有代码

元类在两个类上查找prepare的实现,然后用调用superclass.prepare的子类prepare覆盖子类prepare,该子类后跟subclass.prepare

class MetaHandler(type):
    def __new__(cls, name, bases, attrs):
        instance = type.__new__(cls, name, bases, attrs)
        super_instance = super(instance, instance)
        if hasattr(super_instance, 'prepare') and hasattr(instance, 'prepare'):
            super_prepare = getattr(super_instance, 'prepare')
            sub_prepare = getattr(instance, 'prepare')
            def new_prepare(self):
                super_prepare(self)
                sub_prepare(self)
            setattr(instance, 'prepare', new_prepare)
        return instance


class BaseHandler(object):
    __metaclass__ = MetaHandler
    def prepare(self):
        print 'BaseHandler.prepare'


class SubHandler(BaseHandler):
    def prepare(self):
        print 'SubHandler.prepare'

使用它看起来像这样:

>>> sh = SubHandler()
>>> sh.prepare()
BaseHandler.prepare
SubHandler.prepare

告诉开发人员定义prepare_hook而不是prepare,但是 告诉用户调用prepare

class BaseHandler(object):
    def prepare(self):
        self.prepped = 1
        self.prepare_hook()
    def prepare_hook(self):
        pass

class SubBaseHandler(BaseHandler):
    def prepare_hook(self):
        pass

foo = SubBaseHandler()
foo.prepare()

如果您想要更复杂的多个子类prepare调用链接,那么您的开发人员应该真正使用super,因为这正是它的目的

相关问题 更多 >