Given the following structure where I want a method with a common name for each class, but each derived class needs an additional piece of information in order to form the appropriate result. Descending the inheritance tree accumulates additional needed arguments, but always needs all parents arguments as well.
class A:
@classmethod
def foo(cls, a):
return a
class B(A):
@classmethod
def foo(cls, a, b):
return '.'.join([super().foo(), b])
class C(B):
@classmethod
def foo(cls, a, b, c):
return '.'.join([super().foo(), c])
>>A.foo('a')
'a'
>>B.foo('a','b')
'a.b'
>>C.foo('a','b','c')
'a.b.c'
Is this a frowned upon structure since the LSP does not hold? Is there a different overall design approach that would allow a common function name to account for additional arguments like this in some way?
In this example I am using class methods, but same question could be asked for normal instance methods as well.
Updated Example:
In my case I have a messaging application with some message classes defined in an inheritance hierarchy. Each message type has a specific topic address that needs zero or more runtime parameters such as the node or workflow name. In addition each message has its own set of instance data field attributes.
class BaseMessage:
sending_process: str
@classmethod
def topic(cls):
return 'message'
class WorkflowMessage(BaseMessage):
@classmethod
def topic(cls, node, workflow_name):
return '.'.join([super().topic(), 'workflow', node, workflow_name])
@dataclass
class WorkerServiceMessage(WorkflowMessage):
dataA: str
dataB: str
@classmethod
def topic(cls, node, workflow_name, worker_name):
return '.'.join([super(node, workflow_name).topic(), worker_name])
class Worker:
def __init__(node, workflow, name):
self._node = node
self._workflow = workflow
self._name = name
self.messenger = Messenger()
self.messager.listen(topic=WorkflowMessage.topic(self._node, self._workflow),
callback=self._on_msg)
def _on_msg(self, msg):
self.messenger.publish(topic=WorkerServiceMessage.topic(self._node, self._workflow, self._name),
msg=WorkerServiceMessage(dataA='abc', dataB='123')
worker=Worker('mynode', 'workflowA', 'worker1')
worker.messenger.run()