父类方法调用父方法,而不是子类方法

时间:2019-05-10 21:23:13

标签: python python-3.x inheritance

子类方法是否可以防止父类调用另一个子方法,而是调用父类的方法?

这是我指的代码示例:

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()

这可能吗?

2 个答案:

答案 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.ffB.ff签名不匹配,即使您清理B以更好地支持继承,让AA继承也可能不是一个好主意。 / 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