如何确保我的类方法在子类重写时仍被调用?
举个例子,我有一个
class BaseHandler(object):
def prepare(self):
self.prepped = 1
我不想让每个从BaseHandler继承的类,以及那些想要实现prepare方法的类,都必须记得去调用
super(SubBaseHandler, self).prepare()
有没有办法确保即使子类也实现了prepare方法,父类的方法仍然会被执行呢?
5 个回答
3
你只需要接受一个事实:当别人想要修改你写的类的时候,必须告诉他们要调用基类的方法。其他的解决办法要么需要你再给他们解释别的事情,要么就是一些不太符合Python风格的技巧,这些技巧也可能会被绕过。
Python的对象继承模型是设计得很开放的,试图去改变这个模型只会让问题变得复杂,而这个问题其实根本就不存在。你只需要告诉使用你代码的人,要么遵循你的“规则”,要么程序就会出问题。
4
告诉你的开发人员定义一个叫做 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
,因为这正是它的用途。
16
我用元类解决了这个问题。
使用元类可以确保实现BaseHandler
的人,所有的子类都会调用父类的prepare()
方法,而不需要对现有的代码做任何修改。
这个元类会检查两个类中是否有prepare
方法的实现,然后把子类的prepare
方法替换成一个新的方法,这个新方法会先调用父类的prepare
,然后再调用子类的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