在继承(抽象)类时,如何处理微小但影响深远的实现差异?

时间:2018-10-11 21:11:49

标签: python oop inheritance abstract-class

我对如何处理这个问题感到有些困惑。

比方说,我有一个websocket客户端的以下抽象类和一个实现其大多数方法的子类。
如果Websocket提供程序需要您更改路径(例如/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)

0 个答案:

没有答案