【问题标题】:Defining a subclass exclusively for a slightly different data structure专门为稍微不同的数据结构定义子类
【发布时间】:2019-01-01 10:41:46
【问题描述】:

我决定开始使用 OOP 来使我的代码更加模块化,但我仍然需要学习很多关于最佳实践的知识。

当前数据结构

在这种特殊情况下,我试图定义一个类层次结构,以处理(在最低级别)各种传感器的二进制示波器数据。独立于传感器特性,我定义了 ScopeData 类,它只读取二进制文件并返回 x 和 y 数据以及一些通用特性:

classdef ScopeData

    properties
        Filename
        xdata
        ydata
    end

    properties (Access = private)
        % Some properties only used to extract data from the binary file
    end

    properties (Access = protected)
        fid = -1 % used in reading data and closing upon destruction

        % Properties that are required to quickly navigate to the data
        % locations in the binary file
    end

    properties (Dependent = true)
        Raw % raw data 
    end

    %% Methods related to constructing/destructing
    methods
        function obj = ScopeData(filepath)

            % Input argument checking is done here

            % Assign the filename
            obj.Filename = filepath;

            % Open the file and read its contents
            obj.Open;
            obj.Read;
        end


        function obj = Open(obj)
            % Opens obj.Filename and extracts all info required to read out
            % the data
        end

        function obj = Read(obj)
            rawdata = obj.Raw; % get the raw data

            % Some minimal processing and averaging to get xdata and ydata
            obj.xdata = SomeFunction(rawdata);
            obj.ydata = SomeOtherFunction(rawdata);

        end
    end

    %% Get/set methods
    methods
        function rawdata = get.Raw(obj)
            % uses the private properties to efficiently extract the raw data
        end
    end

end

对于每种不同类型的传感器,我创建了继承自 ScopeData 的子类 SensorXYZData。它们的附加属性都是特定传感器独有的,用于进一步处理数据,例如:

classdef SensorXData < ScopeData

    properties
        % Sensor-specific properties
        SensorLocation
        SensorConfiguration
    end

    properties (Dependent = true)
        % Sensor-specific dependent properties
    end

    methods
        function obj = SensorXData(filepath, SensorLocation, SensorConfiguration)
            % Initialize object
            obj = obj@ScopeData(filepath);

            % Assign sensor-specific properties

            % Do some additional processing

        end
    end

    methods
        % Get/set methods for the dependent properties
    end

end

上面的数据结构允许我为我的每个传感器定义单独的对象,这些传感器都读取一个二进制文件。我目前为每个传感器系列制作类文件之外的对象数组。未存储原始数据,但可以轻松请求。

我想要做什么

在不同的传感器系列中,只有 SensorX 系列将处理单个数据文件(默认)和每个传感器的多个数据文件(不同类型的实验)。 在每个文件的基础上,后者将需要与前者完全相同的处理,但还会有多个文件专用的附加属性和处理步骤。

我目前正在尝试通过拥有一个继承自 SensorXData 的附加子类 SensorXArrayData 来实现这种特殊情况:

classdef SensorXArrayData < SensorXData

    properties
        ExtraProperties
    end

    properties (Dependent = true)
        % Dependent variables specific to this data
    end

    methods
        function obj = SensorXArrayData(MultipleFilepaths, SensorLocation, SensorConfiguration, ExtraProperties)
            % Initialize object - I am only allowed to call obj@SensorXData once, so this currently doesn't work.
            obj = obj@SensorXData(MultipleFilepaths, SensorLocation, SensorConfiguration);

            % Assign the extra properties

            % More processing that is specific

        end
    end

    methods
        % Get/set methods for the dependent variables
    end

end

为了使上述方法发挥作用,需要采取一些额外的步骤,我正在尝试找出最合适的方法。

其中一个选项似乎是使ScopeData 超类与多文件输入兼容并从那里开始工作。还有一种方法可以让ScopeDataSensorXData 保持不变吗?

【问题讨论】:

  • 所有这些问题都是主观的,并且高度依赖于您的实际应用,您没有详细说明。即使你有,它仍然是一个完全主观的评估。如果这是你需要做的以获得必要的功能,那就去做吧。它没有意义。我不太确定您希望听到什么。
  • @excaza 您希望提供哪些其他详细信息以使其更具体?我很好奇如何用不同风格的数据解决我的“所需子类”问题。发现我目前尝试构建工具的方式(不可能)也应该自动回答我当前的实现是否有意义。
  • 什么想要的子类问题?我们所拥有的只是“但是,我无法让构造函数工作”。请参阅:minimal reproducible example。你有一个(不清楚的)客观问题隐藏在一堆主观问题中。如果您的实现实现了所需的行为,那么它是有道理的。我不确定您希望其他人如何为您判断,或者您希望我们使用什么标准来做出这样的判断。
  • 如果你想把SensorXArrayData 当作一个单独的对象,你应该只调用一次超类的构造函数。听起来您应该只重新实现将 properties 视为数组而不是标量的方法(即,与其拥有存储单个数据文件字符串的属性,不如让该属性存储数据文件的单元数组字符串)。您可能根本不需要新课程;只是泛化SensorXData的构造函数/方法来处理数据文件的数组。
  • @excaza 感谢您的指点。我已经更新了我的帖子。希望这更清楚。

标签: matlab class oop inheritance subclass


【解决方案1】:

我认为您正在寻找的是在您的课程中“实现接口”(Java 术语)。它在 MATLAB 中的工作方式是使用multiple inheritance,如下所示:

classdef ClassName < SuperClass1 & SuperClass2

我相信近年来OOP中的共识就是所谓的“composition over inheritance”,基本上就是说你应该关注你的类做什么而不是你的类是。

如何将此应用于您的问题?

添加几个如下所示的类:

classdef (Abstract) SomeFeatureInterface < handle
% This is a specialized interface for doing operation XYZ.
  properties (Abstract = true, Access = protected, Constant = true)
    SOME_CONSTANT;
  end  

  methods (Abstract = true, Access = public) % This doesn't have to be abstract, you can add a
    outName = methodName(obj)                % default implementation if relevant.
  end
  
end

然后您的派生类的声明将看起来像购物清单,也就是说,您可以通过从相关接口(抽象)类继承来直接从类声明中添加所需的功能:

classdef SensorXData < ScopeData & SingleFileInterface & MultiFileInterface

classdef SensorYData < ScopeData & SingleFileInterface

这样,SensorXData 将包含处理多个文件的相关功能,而SensorYData 则不会。此外,这将确保浅继承,这被认为是好的。

【讨论】:

  • 谢谢。这似乎是一个不错的方法。将接口真正变成通用数据读取类和特定传感器类之间的层是否有意义?即 SingleFileInterfaceMultiFileInterface 继承自重写的 ScopeData 类,而 SensorXYZData 类则继承自 SingleFileInterface 和/或 MultiFileInterface(不再来自 ScopeData)。
  • 这被认为是个坏主意,请参阅:“deadly diamond of death”。这些接口充当“mix-ins”,通常是顶级类。
  • 如果出于某种原因,您确实认为钻石是唯一的出路,那么有一些关于如何避免其致命性的讨论here
  • 很高兴知道。我已将您的答案标记为已接受。这将是我要尝试追求的方法。谢谢!
猜你喜欢
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 1970-01-01
相关资源
最近更新 更多