I am coming from C# background and in order to implement a strategy pattern, we would always use an interface, for example: ILoggger. Now as I understand, in duck-typed languages such as Python, we can avoid this base class/contract.
My question is, is this the best way to implement a strategy pattern by taking advantage of duck typing? And, does this duck typing way of doing this make it clear to the next user of my code that this is an "point of extension"? Also, I think it is better to use type hints to help the next person looking at your code to see what the type of the strategy should be, but with duck-typing without base class/contract, which type do you use? One of the already concrete classes?
Here is some code:
class FileSystemLogger():
def log(self, msg):
pass
class ElasticSearchLogger():
def log(self, msg):
pass
# if i wanted to use type hints, which type should logger be here?
class ComponentThatNeedsLogger():
def __init__(self, logger):
self._logger = logger
# should it be this?
class ComponentThatNeedsLogger():
def __init__(self, logger : FileSystemLogger):
self._logger = logger
Could someone please advise what is the most standard/Pythonic/readable way to handle this?
I am not looking for the "here is answer in 2 lines of code" answer.