2009-12-12

How to handle multiple inheritance of ABCs that implement each others abstract methods

Let's say I have two ABCs, NeedA and NeedB, that implement each others' abstract methods:

class NeedA(metaclass=abc.ABCMeta):
  @abc.abstractmethod
  def need_A(self):
    pass
  def need_B(self):
    pass

class NeedB(metaclass=abc.ABCMeta):
  @abc.abstractmethod
  def need_B(self):
    pass
  def need_A(self):
    pass
Now, how do you create a subclass, through multiple inheritance, that inherits both ABCs such that their abstract method requirements are met by each other? You can't do the naive solution of inheriting both because whomever comes first in the inheritance chain will trigger a TypeError:

class SubClass(NeedA, NeedB):
  pass

SubClass()  # Raises TypeError for NeedA.need_A not being implemented.


The TypeError is triggered because NeedA.need_A() shadows NeedB.need_A(), preventing the abstract method from being implemented.

Luckily it is easy to get around this:

class SubClass(NeedA, NeedB):
  need_A = NeedB.need_A


By explicitly pulling up into the subclass the shadowed method needed to meet the abstract method requirement you fix the error. This trick works because class statements essentially execute the code contained within them, making any created variables class variables; this obviously includes assignment.

I came across this problem myself and it took my a second to figure out how best to solve it w/o trying some crazy metaclass that searched both up and down the inheritance tree looking for methods that implement an abstract method.