Python – Pattern for subclass overload with different arguments

asyncdesign-patternsliskov-substitutionpythonpython-3.x

I'm in the process of writing an bidirectional, asynchronous socket server and server handler. The base handler class I'm working off of is as follows:

class BaseAsyncSocketHandler:
    async def send(self, data: bytes) -> int

However, I want to write a subclass that sends two arguments, an event and arbitrary corresponding data, which suggests the signature:

   async def send(self, event: str, data: object) -> int:
       return await super().send(event_data_magic_to_bytes(event, data))

Unfortunately, this violates the Liskov substitution principle, and I don't think writing it as a mixin will makes the situation any better, so I'm hoping somebody has either seen this before or can think of a better design pattern (or tell me this is an unnecessary abstraction in the first place).

Best Answer

In the end, I settled on providing the following:

class BaseAsyncSocketHandler:

    async def _send(self, data: bytes) -> int:
        ...

    @abc.abstractmethod
    async def send(self, *args, **kwargs) -> int:
        pass

This way the user can implement subsets of the send method while using the base send method provided by the socket wrapper. As to why I wanted to use send instead of just creating another class method like send_event, I think I mostly just wanted the interface to the class to remain compact and usable while allowing for different socket methodologies.

Related Topic