子类方法是否可以防止父类调用另一个子方法,而是调用父类的方法?
这是我指的代码示例:
class A:
def f(self):
return 'Af'
def ff(self, var):
return var + 'ff ' + self.f()
class B(A):
def f(self):
return 'Bf'
def ff(self):
return super().ff('B')
print(B().ff())
输出为Bff Bf
我希望它是:Bff Af
换句话说,当调用B.f()
时,如果调用类是A.f()
,我想将调用重定向到A
。
如果调用的类是B
,则调用B.f()
。
这可能吗?
答案 0 :(得分:1)
这里的问题是您尚未为继承设计A
。为了使方法重写能够正常工作并且不会产生不可预期的副作用,您需要仔细考虑并记录哪些方法取决于其他方法。
此外,在B.ff
接受0个参数而A.ff
接受一个参数的情况下,您也严重违反了Liskov替换法。
您在这里有三个主要选择。一种是改用合成:
class B:
def __init__(self):
self.a = A()
def f(self):
return 'Bf'
def ff(self):
return self.a.ff('B')
现在B.f
对任一类的ff
均无效。考虑到A.ff
和B.ff
签名不匹配,即使您清理B
以更好地支持继承,让A
从A
继承也可能不是一个好主意。 / p>
选项2决定f
是自定义ff
的钩子。在这种情况下,您将保留当前的A
实现和行为,并且如果子类想要分别自定义ff
,则它们需要以一种不依赖于A.ff
的方式覆盖它:
class B(A):
def f(self):
return 'Bf'
def ff(self):
return 'Bff ' + super().f()
选项3决定覆盖f
不应影响ff
。在这种情况下,A.ff
需要以不受替代影响的方式调用A.f
。例如,A.ff
可以将f
而不是A.f
称为self.f
:
class A:
def f(self):
return 'Af'
def ff(self, var):
return var + 'ff ' + A.f(self)
然后,您现有的B
将按预期工作。该选项可能是选项1的亚军。
答案 1 :(得分:0)
您可以通过不使用继承(而使用合成)来轻松实现它:
class A:
def f(self):
return 'Af'
def ff(self, var):
return var + 'ff ' + self.f()
class B:
def __init__(self):
self.a = A()
def f(self):
return 'Bf'
def ff(self):
return self.a.ff('B')
print(B().ff())
输出:
Bff Af