Проблема в том, что вы не разработали A
для наследования.Чтобы переопределение методов работало корректно и без непредсказуемых побочных эффектов, вам необходимо тщательно продумать и документ , какие методы зависят от других методов.
Кроме того, у вас есть серьезное нарушение подстановки Лискова втот факт, что B.ff
принимает 0 аргументов, когда A.ff
принимает один.
У вас есть три основных варианта здесь.Вместо этого нужно использовать композицию:
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
для лучшей поддержки наследования.
Вариант 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.