我有一个课程BasicEvidenceTarget
和SchedulableSoma
。有时我会从SchedulableSoma, BasicEvidenceTarget
继承,有时我只从SchedulableSoma
继承。当我继承SchedulableSoma, BasicEvidenceTarget
时,我希望SchedulableSoma
覆盖方法BasicEvidenceTarget.inject_basic_evidence
。这样做的好方法是什么?
覆盖如下:
class SchedulableSoma(SchedulableCluster, Soma):
# This is a possible overload of this method in BasicEvidenceTarget.
def inject_basic_evidence(self, *args, **kwargs):
super().inject_basic_evidence(*args, **kwargs)
self.ask_for_reschedule()
现在我无条件地覆盖了基类方法,因此如果它不存在,则会有一些方法污染:如果调用了覆盖,则调用super将失败。有条件地生成覆盖会更好。
我觉得有__prepare_subclass__
魔法可能有用,但我不确定该怎么做。
答案 0 :(得分:3)
您可以使用工厂函数在定义继承它的类时生成适当的类。这只是一个草图:
def makeSubclass(otherclass):
class MixedClass(otherclass):
if otherClass == BasicEvidenceTarget:
def inject_basic_evidence(...):
# ...
elif otherClass == WhateverOtherClass:
def some_other_method(...):
# ...
然后你会这样做:
class SchedulableSoma(makeSubclass(BasicEvidenceTarget)):
# ...
另一种可能性是简单地定义SchedulableSoma中的所有方法,但包括对它们的检查,如果当前实例不从相应的类继承,则会引发异常。类似的东西:
class SchedulableSoma(object):
def inject_basic_evidence(self, *args, **kwargs):
if not isinstance(self, BasicEvidenceTarget):
raise TypeError("Cannot call inject_basic_evidence unless you inherit from BasicEvidenceTarget")
def some_other_method(self, *args, **kwargs):
if not isinstance(self, SomeOtherClass):
raise TypeError("Cannot call some_other_method unless you inherit from SomeOtherClass")
# similar checks for other classes
这样,对inject_basic_evidence
的调用将立即失败,并显示更具体的错误消息,而不是在super
调用失败时使用更加模糊的消息"超级对象没有属性& #34;等等。
最终,您可能想要考虑是否有更健壮的方法来构建类层次结构。根据某些其他类是否也出现在继承层次结构中,让类改变自己的行为有点神奇,它可能会使用户感到困惑或导致不同类别之间的不可预见的交互。
答案 1 :(得分:1)
如果没有有趣的元类业务,你在课堂定义时不可能做到这一点。这可以在实例创建时使用以下代码完成:
class SchedulableSoma(SchedulableCluster, Soma):
def __init__(self,*args,**kwargs):
super().__init__(self,*args,**kwargs)
if hasattr(self,"inject_basic_evidence"):
def inject_basic_evidence(*args, **kwargs):
super().inject_basic_evidence(*args, **kwargs)
self.ask_for_reschedule()
self.inject_basic_evidence = inject_basic_evidence
注意:如果SchedulableSoma
的子类覆盖inject_basic_evidence
答案 2 :(得分:-1)
我认为这个问题可以通过不同的继承模式来解决。用你的想法:
class YourClass(SchedulableSoma, BasicEvidenceTarget):
def inject_basic_evidence(self, *args, **kwargs):
if isinstance(self, BasicEvidenceTarget):
BasicEvidenceTarget.inject_basic_evidence(self, *args, **kwargs)
else:
super().inject_basic_evidence(*args, **kwargs)
self.ask_for_reschedule()
或者
class YourClass(SchedulableSoma, BasicEvidenceTarget):
if issubclass(YourClass, BasicEvidenceTarget):
def inject_basic_evidence(self, *args, **kwargs):
super().inject_basic_evidence(*args, **kwargs)
self.ask_for_reschedule()