I am trying to create a simple abstract base class Abstract
that along with its own methods provides the methods of two others abstract base classes: Publisher
and Subscriber
. When I try to initialize the concrete class Concrete
, built on Abstract
I get this error: Cannot create a consistent method resolution order (MRO) for bases ABC, Publisher, Subscriber. What is the right way to do it?
from abc import ABC, abstractmethod
class Publisher(ABC):
subscribers = set()
def register(self, obj):
self.subscribers.add(obj)
def unregister(self, obj):
self.subscribers.remove(obj)
def dispatch(self, event):
print("dispatching", event)
class Subscriber(ABC):
@abstractmethod
def handle_event(self, event):
raise NotImplementedError
class Abstract(ABC, Publisher, Subscriber):
@abstractmethod
def do_something(self, event):
raise NotImplementedError
class Concrete(Abstract):
def handle_event(self, event):
print("handle_event")
def do_something(self, event):
print("do_something")
c = Concrete()
Abstract classes don't have to have abc.ABC
in their list of bases. They have to have abc.ABCMeta
(or a descendant) as their metaclass, and they have to have at least one abstract method (or something else that counts, like an abstract property), or they'll be considered concrete. (Publisher
has no abstract methods, so it's actually concrete.)
Inheriting from ABC
is just a way to get ABCMeta
as your class's metaclass, for people more comfortable with inheritance than metaclasses, but it's not the only way. You can also inherit from another class with ABCMeta
as its metaclass, or specify metaclass=ABCMeta
explicitly.
In your case, inheriting from Publisher
and Subscriber
will already set Abstract
's metaclass to ABCMeta
, so inheriting from ABC
is redundant. Remove ABC
from Abstract
's base class list, and everything should work.
Alternatively, if you really want ABC
in there for some reason, you can move it to the end of the base class list, which will resolve the MRO conflict - putting it first says you want ABC
methods to override methods from the other classes, which conflicts with the fact that the other classes are subclasses of ABC
.