Search code examples
pythonoopinheritanceoverridingmultiple-inheritance

Method overriding in python class multiple inheritance


I have a Base class that is inherited by two classes Adder and subtractor in which I have overridden the method called test_func() to adapt to respective class properties.

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

I am writing a superclass called Algebra that inherits both Adder and Subtractor.

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

Now I want to use the test_func() method selectively from Adder or Subtractor in the superclass Algebra. Is there a way in which I can do this? I tried

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

but it only takes method from Adder class. Is ther a way I can tell the superclass which class to evaluate the method from? For example,

G.test_func('Adder')

Solution

  • The only way to get this result would be to redefine Algebra.test_func() to make it explicitly work that way, 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)
    

    BUT this is a complete mess and a perfect example of inheritance abuse. Inheritance implies a "is a" relationship, and this means that any subclass of Base should keep a compatible interface (the same client code must be able to work the same with instances of whatever Base subclass) - which the above doesn't.

    Now ask yourself: is an Algebra an Adder and a Subtractor ? If yes, then your design issue is with test_func() itself. Else (an Algebra has an Adder and a Subtractor), do not inherit from Adder and Subtractor but use composition/delegation instead.