Search code examples
pythoninheritancemultiple-inheritancemethod-resolution-orderlinearization

How to write let two Python abstract classes implement each other's abstract methods?


Suppose you have abstract classes A1 and A2. Each of them has an abstract method and a concrete method.

from abc import ABC, abstractmethod

class A0(ABC):
    pass

class A1(A0, ABC):
    def foo(self):
        return 1

    @abstractmethod
    def bar(self):
        raise NotImplementedError()


class A2(A0, ABC):
    @abstractmethod
    def foo(self):
        raise NotImplementedError()
    
    def bar(self):
        return 10

Now you want to mix-in them togather to implement each other's abstract method:

class C(A2, A1, A0):
    def all(self):
        return (super().foo(), super().bar())


C().all()

However the above code does not work because I got the following error:

TypeError: Can't instantiate abstract class C with abstract method foo

How can I create C so that it can mix-in both A1 and A2?


Solution

  • This is a solution similar to Gábor Fekete, except that the abstract methods are extracted to new ABC's, to avoid changing A0.

    from abc import ABC, abstractmethod
    
    class A0(ABC):
        pass
    
    class AbstractFoo(A0, ABC):
        @abstractmethod
        def foo(self):
            raise NotImplementedError()
    
    class AbstractBar(A0, ABC):
        @abstractmethod
        def bar(self):
            raise NotImplementedError()
    
    class A1(AbstractFoo, AbstractBar, A0, ABC):
        def foo(self):
            return 1
    
    class A2(AbstractFoo, AbstractBar, A0, ABC):
        def bar(self):
            return 10
    
    class C(A2, A1, A0):
        def all(self):
            return (super().foo(), super().bar())
    
    C().all()