Как обрабатывать небольшие, но далеко идущие различия в реализации при наследовании (абстрактных) классов? - PullRequest
0 голосов
/ 12 октября 2018

Я немного озадачен тем, как справиться с этим.

Допустим, у меня есть следующий абстрактный класс клиента веб-сокета и подкласс, который реализует большинство его методов.
Если вместо команды в сообщении провайдеру веб-сокета потребуется изменить пути (как /ws/somesubscription -> /ws/othersubscription).Как бы я поступил и реализовал это без определения нового метода в подклассе, который в противном случае был бы почти таким же?

Моя цель, которую я хочу достичь, состоит в том, чтобы мой код оставался сухим, при этом гибко определяя конкретные реализации.

from abc import ABC, abstractmethod
from some_library import some_websocket_client

class WebsocketClientBase(ABC):

    def __init__(self):
        self.some_implementation_data = None
        self.some_other_data = None
        self.ws = None

    @abstractmethod
    def start_socket(self):
        self.ws = some_websocket_client()

    @abstractmethod
    def send_a_message(self, message):
        pass

    @abstractmethod
    def websocket_message(self, message_data):
        if not self.ws:
            self.start_socket()
        url = self.some_implementation_data['url']
        message = message_data['msg']
        command = message_data['ws_command']
        self.ws.send("{'command': {command}, 'message': {message}, 'url': {url}".format(command=command, url=url, message=message))
        some_websocket_client.send(message)


class SomeWSClient(WebsocketClientBase):
    # This subclass inherits almost everything, except its specific implementation data

    def __init__(self):
        super().__init__()
        self.some_implementation_data = {'url': 'some_url'}

    def start_socket(self, message):
        super().start_socket(message)

    def send_a_message(self, message):
        message_data = {
            "msg": "my message",
            "ws_command": "subscribe"
        }
        self.websocket_message(message_data)

    def websocket_message(self, message_data):
        super().websocket_message(message_data)


class ProblemWSClient(WebsocketClientBase):
    # Here I encounter problems

    def __init__(self):
        super().__init__()
        self.some_implementation_data = {'url': 'some_url'}

    def start_socket(self, message):
        super().start_socket(message)

    def send_a_message(self, message):
        message_data = {
            "msg": "my message",
            "ws_command": "subscribe"
        }
        self.websocket_message(message_data)

    def websocket_message(self, message_data):
        # I need to repeat this, because I can't call the superclass
        if not self.ws:
            self.start_socket()

        # Here I need to apply the new functionality, although largely the same.  
        command = message_data['ws_command']
        url = self.some_implementation_data['url'] + command
        message = message_data['msg']

        self.ws.send("{'message': {message}, 'url': {url}".format(command=command, url=url, message=message))
        some_websocket_client.send(message)
...