8

I need two levels of abstract classes and a third level concrete class:

from abc import ABC

class Shape(ABC):
...

class Quad(ABC, Shape):
...

class Square(Quadrilateral)
...

This code generates TypeError: Cannot create a consistent method resolution against the declaration of Quad. I realize that the problem is a multiple inheritance ambiguity. Quad doesn't know whether to derive certain functions directly from ABC or from Shape, but how do I fix it? I can't drop ABC from Quad's declaration because then it won't be abstract anymore.

Keith Wiley
  • 683
  • 2
  • 6
  • 14

2 Answers2

5

Apparently, simply reversing the order of the parent classes to Quad fixes the problem. I'm still unclear on the underlying theory (although it can sort of be inferred), but at least my code is running now.

class Quad(Shape, ABC)
Farvardin
  • 5,336
  • 5
  • 33
  • 54
Keith Wiley
  • 683
  • 2
  • 6
  • 14
  • The underlying theory is python's Method Resolution Order algorithm; see here: python.org/download/releases/2.3/mro Long story short, the MRO algorithm enforces that left classes appear before right classes in the MRO, and also that, if X appears before Y in the MRO of an ancestor class, X will appear before Y in the MRO of the descendant class. There is no way to meet both conditions for `Quad` in the original post, but there is a way in this answer (namely: `Quad`, `Shape`, `ABC`). – Damien Jan 20 '23 at 17:27
1

This is explained in abc documentation:

Note that the type of ABC is still ABCMeta, therefore inheriting from ABC requires the usual precautions regarding metaclass usage, as multiple inheritance may lead to metaclass conflicts. There is also an example how to use ABCMeta directly.

With that your code would look like this:

from abc import ABC

class Shape(metaclass=ABCMeta):
...

class Quad(Shape, metaclass=ABCMeta):
...

class Square(Quadrilateral)
...

I don't know why it worked when ABC is the last class in the list, but the benefit of using ABCMeta is that you cannot put it at the beginning of the list.

tcb
  • 2,745
  • 21
  • 20