Переопределение метода в множественном наследовании класса python - PullRequest
1 голос
/ 08 января 2020

У меня есть класс Base, который наследуется двумя классами Adder и subtractor, в котором я переопределил метод, названный test_func(), для адаптации к соответствующим свойствам класса.

class Base():
    def __init__(self, K):
        self.K = K
    def test_func(self):
        'Must be overridden since used by another_func()'
        return self.K
    def another_func(self):
        return self.K * self.test_func()

class Adder(Base):
    def __init__(self, K, M):
        Base.__init__(self, K)
        self.M = M
    def test_func(self):
        return self.M + self.K

class Subtractor(Base):
    def __init__(self, K, N):
        Base.__init__(self, K)
        self.N = N
    def test_func(self):
        return self.N - self.K

Я пишу суперкласс с именем Algebra, который наследует Adder и Subtractor.

class Algebra(Adder, Subtractor):
    def __init__(self, K, M, N):
        Adder.__init__(self, K, M)
        Subtractor.__init__(self, K, N)

Теперь я хочу использовать метод test_func() выборочно из Adder или Subtractor в суперкласс Algebra. Есть ли способ, которым я могу сделать это? Я пытался

G = Algebra(K=2, M=5, N=7)
G.test_func()
>> 7

, но он принимает метод только из класса Adder. Можно ли сказать суперклассу, из какого класса будет оцениваться метод? Например,

G.test_func('Adder')

Ответы [ 3 ]

1 голос
/ 08 января 2020

Единственный способ получить этот результат - переопределить Algebra.test_func(), чтобы он явно работал таким образом, ie:

class Algebra(Adder, Subtractor):
    def __init__(self, K, M, N):
        Adder.__init__(self, K, M)
        Subtractor.__init__(self, K, N)

    def test_func(self, which):
        if which == "Adder"):
            return Adder.test_func(self)
        elif which == "Subtractor":
            return Subtractor.test_func(self)
        else:
            raise ValueError("don't know %s" % which)

НО это полный беспорядок и прекрасный пример наследования злоупотребление. Наследование подразумевает отношение «является», и это означает, что любой подкласс Base должен поддерживать совместимый интерфейс (один и тот же клиентский код должен работать одинаково с экземплярами любого подкласса Base), что выше 't.

Теперь спросите себя: Algebra это Adder и Subtractor? Если да, то ваша проблема дизайна связана с самой test_func(). Иначе (Algebra имеет Adder и Subtractor), не наследуйте от Adder и Subtractor, но вместо этого используйте состав / делегирование.

1 голос
/ 08 января 2020

Не переопределять test_func; предоставить два метода, каждый из которых вызывает test_func.

class Algebra(Adder, Subtractor):
    def __init__(self, K, M, N):
        Adder.__init__(self, K, M)
        Subtractor.__init__(self, K, N)

    def test_adder_func(self):
        return Adder.test_func(self)

    def test_subtractor_func(self):
        return Subtractor.test_func(self)

нужного родительского класса. Я игнорирую любой более глубокий вопрос, например, почему вы выбрали множественное наследование.

0 голосов
/ 08 января 2020

Способ наследования работает

  1. Большую часть времени вы будете иметь ссылку на родительский класс
  2. Инстанцирование с дочерним классом

В вашем случае вместо

G = Algebra(K=2, M=5, N=7)

Вы должны сказать

G = Adder(K=2, M=5, N=7)

и затем вызвать соответствующую функцию с помощью G.test_func()

В вашем примере среда выполнения никогда не узнает, как вызвать дочерний метод, потому что вы создали экземпляр родительского объекта.

...