繁体   English   中英

如何正确安排一组课程?

[英]How to organize a set of classes properly?

我想通过继承创建一组对象,并且需要一些建议来组织实现。

所有对象都必须继承自BaseObject ,如下所示:

class BaseObject:
    class Actuator:
        pass
    class Sensor:
        pass

我想确保从BaseObject继承的所有对象都必须具有类Actuator和类Sensor

然后,我有了另一个抽象级别,其中包含一些泛型对象,例如:

class Camera(BaseObject):
    class Actuator:
        pass
    class Sensor:
        def get_frame():
            pass
        def set_parameter():
            pass

我希望我创建的每个Camera对象至少具有get_frameset_parameters

我想强制实现这些类/函数,以便为每个新对象保留相同的合成器,因此,如果要与其他摄像机一起使用,可以保留以前的脚本,只需要创建一个新的Camera对象即可。 您还应该知道,这些类不会被直接实例化,而是可以建立的。

我看了元类,看上去很不错,可以强制在类中实现方法,但是我不确定是否:

  • 您可以从元类BaseObject创建元类( Camera
  • 您可以强制执行一类的元类(如ActuatorBaseObject (通过),以及如何@abc.abstractmethod ?)
  • 您可以在元类内部的类中强制执行方法? (如get_frame()
  • 真的是唯一的方法还是我应该完全不同地组织我的课程?
  • 我是否应该再去制作纸飞机? (请不要回答这个)

我会这样实现它们:

from abc import ABCMeta

class BaseObject:
    __metaclass__ = ABCMeta
    def __init__(self):
        self.actuator = self._get_actuator()
        self.sensor = self._get_sensor()
    @abstractmethod
    def _get_actuator(self):
        return 'actuator'
    @abstractmethod
    def _get_sensor(self):
        return 'sensor'

每个子类都有一个执行器和一个传感器参数。 如果您在子类中重写__init__ ,请确保调用super.__init__ __init__

Class Sensor:
    __metaclass__ = ABCMeta
    pass

class CameraSensor(Sensor):
    __metaclass__ = ABCMeta
    @abstractmethod
    def get_frame():
        pass
    @abstractmethod
    def set_parameter():
        pass

class Camera(BaseObject):
    def _get_sensor(self):
        # get the sensor
        assert issubclass(sensor, CameraSensor)

我想强制实现这些类/函数,以使每个新对象都保持相同的语法,因此,如果要使用其他摄像机,可以保留以前的脚本,只需要创建一个新的Camera对象即可。

OT:您真的是说“对象”(=>实例)还是子类? 但无论如何:

由于您提到“传感器”和“执行器”不一定要针对不同的BaseObject子类具有相同的接口,因此我们BaseObject忽略整个BaseObject部分,而专注于Camera部分。

如果我理解正确,那么您想要的是通用Camera类型。 该类型必须具有sensoractuator属性,它们都必须遵守给定的接口,但可能具有不同的实现方式。

至此,我们(至少,至少是我)没有足够的上下文来决定我们是否需要抽象BaseCamera类型,还是仅需要抽象BaseCameraSensorBaseCameraActuator接口。 可以确定的是,我们确实需要BaseCameraSensorBaseCameraActuator所以让我们开始吧。 我认为传感器和执行器也需要知道它们所属的摄像机,这是FWIW真正尖叫的“战略”模式,因此我们从一个基类开始-我们称之为“ BaseStrategy”-除了获得一个对其宿主对象的引用:

class Strategy(object):
    def __init__(self, parent):
        self._parent = parent

现在,让我们定义“ CameraSensor”和“ CameraActuator”接口:

class BaseCameraSensor(Strategy):
    __metaclass__ = ABCMeta

    @abstractmethod
    def get_frame(self):
        raise NotImplementedError

    @abstractmethod
    def set_parameter(self, value):
        raise NotImplementedError

class BaseCameraActuator(Strategy):
    __metaclass__ = ABCMeta

    @abstractmethod
    def random_method(self):
        raise NotImplementedError

现在,我们可以处理“相机”部分。 如果实现的唯一变体部分封装在SensorActuator (这是策略模式的重点),则我们不需要抽象基类-我们可以将适当的SensorActuator子类作为参数传递给初始化程序:

class Camera(object):
    def __init__(self, brand, model, sensor_class, actuator_class):
        self.brand = brand
        self.model = model

        assert issubclass(sensor_class, BaseCameraSensor)
        self.sensor = sensor_class(self)

        assert issubclass(actuator_class, BaseCameraActuator)
        self.actuator = actuator_class(self)

问题就解决了。 FWIW,请注意,你并不真正需要的Strategy类,也不是ABC的一部分,只是记录了预期的接口sensor_classactuator_class ,让程序崩溃,如果他们不尊重就够了-这就是如何我们在Python编程了对年(就我而言,已超过15年)和JustWork(tm)-但ABC至少使合同更加明确,程序会更快崩溃。 但是请不要上当:它不会使您的代码万无一失(提示:不会,期间)。

现在,如果我们还有其他变体部分,无法提前知道实现,则最简单的解决方案将是遵循相同的模式-委托给实例化时传递的Strategy对象。 因此,重点是:现在我们已经实现了这一点,我们发现我们不需要某些BaseCamera ABC。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM