【问题标题】:Validate property to be a sublclass of an abstract class in MATLAB验证属性是 MATLAB 中抽象类的子类
【发布时间】:2019-07-05 10:15:10
【问题描述】:

我是 Matlab 中的 OOP 的新手,在一般情况下 OOP 方面还很陌生,但我知道我在 C++ 中学到了一些东西。

我正在关注此处Property class and size validation 的 Matlab 文档。我想验证一个属性,使其必须是一个特定的类,并且我正在使用链接中的示例。这是我的班级的样子:

classdef simpoint
   ...
   properties
      ...
      outputType dataType
      ...
   end
   ...
end

在我的代码中,dataType 是我编写的一个类。更重要的是它是抽象的。

我收到了错误

Error defining property 'outputType' of class 'simpoint':
Class dataType is abstract. Specify a default value for property outputType.

dataType 类是抽象的,用于强制用户实现某些方法。我正在尝试使用属性验证来确保在设置outputType 时,该类是dataType 的子类。

我并不想设置默认值,因为忘记设置outputType 会引发错误。

如何验证outputType 以确保它是dataType 的子类?在 Matlab 中有没有更好的方法来做到这一点?

【问题讨论】:

    标签: matlab validation oop


    【解决方案1】:

    这个问题有一个更优雅的解决方案,这显然不是众所周知的。

    MATLAB 有一个Heterogeneous Class Hierarchies 的概念。这只是显式声明公共根类(抽象或非抽象)的奇特方式,以便它可以用于属性验证。实际上,您需要做的就是让您的抽象类继承自matlab.mixin.Heterogeneous

    这是一个简单的例子:

    classdef (Abstract) AbstractItem < handle & matlab.mixin.Heterogeneous
    end
    
    classdef Collection < handle
        properties
            items AbstractItem
        end
    end
    

    那你就没有问题了:

    >> x = Collection
    
    x = 
    
      Collection with properties:
    
        items: [0×0 AbstractItem]
    

    如果没有matlab.mixin.Heterogeneous 继承,您将收到您描述的错误:

    定义类“Collection”的属性“items”时出错。 AbstractItem 类是抽象的。指定属性项的默认值。

    【讨论】:

    • 感谢您添加此答案。我已将其标记为已接受的,因为正如您所说,它更优雅。事实上,在问了这个问题一年左右之后,我发现自己很自然地使用了这种方法!
    • 我花了好几个小时在互联网上搜索,发现很多人都遇到了同样的问题,但没有真正的解决方案。在与 MathWorks 工程师交谈后,我发现了异构类,我觉得有必要在某个地方发表这个发现。这个话题似乎是个好地方:)
    【解决方案2】:

    您当前的代码使用以下逻辑:

    1. 创建一个新的simpoint 对象
    2. 啊,这个对象需要一个outputType 属性
    3. outputType 属性初始化为空的dataType 对象
    4. 呃,我们无法实例化抽象对象 - 错误。

    相反,您也可以使用 setter 和 getter 来验证数据类型。这将删除上面的第 3 步和第 4 步,因为初始属性值将是 []

    classdef simpoint < matlab.mixin.SetGet
        properties
            outputType
        end
        methods 
            % ...
        end
        methods % Setters and getters
            function set.outputType( obj, v )
                % When the 'obj.outputType = X' is called, this function is
                % triggered. We can validate the input first
                assert( isa( v, 'dataType' ) );
                % If the assertion didn't error, we can set the property
                obj.outputType = v;
            end
            function v = get.outputType( obj )
                % Nothing bespoke in the getter (no not strictly needed), just return the value
                v = obj.outputType;
            end
        end
    end
    

    要获得更多信息验证,您可以使用validateattributes 而不是assert

    在这种情况下,outputType 的默认值将是 [],除非您在构造函数中对其进行初始化。

    注意,通过使用matlab.mixin.SetGet 来启用setter 和getter,我已经隐式地将您的对象设为handle。在更广泛的 OOP 术语中,对象现在是“按引用”而不是“按值”访问的。阅读更多here

    如果您不想要句柄,则可以删除 &lt; matlab.mixin.SetGet 并根据您自己的注释,更明确地定义设置器

    function obj = set.outputType( obj, v )
        % Have to return 'obj' if the class isn't a handle.
        % ...
    end
    

    【讨论】:

    • 太好了,感谢您的帮助。那么,有什么理由我不能写一个方法SetOutputType(obj, v) 而不是从matlab.mixin.SetGet 继承,而不是像你在这里定义的那样使用set.outputType(obj, v)?使用matlab.mixin.SetGet 是更好的做法吗?
    • 您的对象有一个属性outputType。我的方式是,您使用thing.outputType = X 设置它,并使用Y = thing.outputType 访问它,并内置可选验证。要使用非本机设置器(如您的评论所示),您必须创建属性private , 否则用户可以在不使用SetOutputType 的情况下设置它,那么您可能还需要一个公共GetOutputType,现在用户知道outputType 是一个属性,但只能通过这些可能未知的辅助函数访问它?所以我认为只是易用性和一致性改进......
    • 我不知道我是否还不清楚 - set.get. 被隐式调用。分配thing.outputType = X 现在会自动调用set( thing, 'outputType', X ),这会触发setter 函数,从而触发验证。
    • 这让我得到了正确的答案,但它仅在 simpoint 是句柄时才有效。如果simpoint 是普通类,那么你需要使用obj = set.outputType( obj, v )
    • @Phill - 这不是真的。 Getter 和 setter 可以在普通类中正常工作。见这里:mathworks.com/help/matlab/matlab_oop/…
    猜你喜欢
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多