One of the ways to cope with the static nature of Singeltons is to hide them behind interfaces. This allows to use Singletons in some clients, but to replace them with substitutes such as Mocks in tests.
Can I make a Python Metaclass Singleton implement an interface?
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class ILogger(ABC):
@abstractmethod
def log(self,message: str) -> None:
pass
class Logger(ILogger,metaclass=Singleton): # won't compile - meta mismatch
def log(self,message: str) -> None:
print("Real Log: ",message)
class FakeLogger(ILogger):
def log(self,message: str) -> None:
print("Fake Log: ",message)
def task1(logger: ILogger):
print("using logger ",id(logger))
logger.log("Task1 error 1 on log ")
When I try I get the following error
metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Do I need to switch to a different python implementation of Singleton such as overriding __new__
to allow the Singleton to implement an interface?