2

在 Matlab 中,我想要一个如下所示的数据结构:

DataStruct
   .model
     .Q
     .Qchol
      .
      .
   .system
      .
      .

该结构很可能是一个类,尽管我并不真正需要 oop 附带的所有其他功能。

但我需要

  • 如果Q分配了一些东西,那么自动Qchol = cholcov(Q).
  • 如果Qchol分配了一些东西,那么自动Q = Qchol' * Qchol.
  • 同时,QQchol都存储用于快速读取访问
  • 并且可以通过简单的赋值写入,例如QQcholDS1.mod.Q = value

我知道我可以model上课,并为 Q 和 Qchol 设置/获取方法。但是,对于两个矩阵(可能还有更多字段)来说,这似乎有点过头了。Matlab 还警告我,我不应该在 set 方法中访问其他属性。

那么:拥有这种数据结构的最佳方式是什么,最好没有警告?

4

2 回答 2

3

您基本上希望赋值 ( DS1.mod.Q = value) 具有副作用,这不可避免地意味着一个 setter,因此是一个类。你应该要么放弃这个要求,要么写一个类。

如果您希望避免在类声明中定义属性,则可以使用Dynamic Properties,它允许您在运行时添加属性(尽管有一些说明性的语法addprop())。

编辑

帕特里克,问题比 M-lint 更深。考虑以下类:

classdef cantInstantiateMe < handle
    properties
        x
        minus_x
    end
    methods
        function obj = cantInstantiateMe(x)
            obj.x = x;   % <-- this calls set.x(), which calls set.minus_x(), which calls set.x(), ...
            obj.minus_x = -x;
        end

        function set.x(obj, value)
            obj.x = value;
            obj.minus_x = -value; % <-- this gives an M-Lint warning
        end

        function set.minus_x(obj, value)
            obj.minus_x = value;
            obj.x = -value;                
        end

    end
end

这个类不能被实例化,因为每个 setter 调用另一个 setter(这不是 Matlab 特定的)。尝试在我的机器上实例化给出:

???达到最大递归限制 500。使用 set(0,'RecursionLimit',N) 更改限制。请注意,超出可用堆栈空间可能会使 MATLAB 和/或您的计算机崩溃。

在这一点上,我认为你有两个选择:

  • 制作 要么Q要么Qchol附属财产. 这将以每次读取访问时重新计算从属属性为代价。
  • 使用一些私有影子属性,例如shadow_Qshadow_Qchol它们将在调用公共属性的 setter 时设置,并在调用它们的 getter 时返回。如同:

     function set.x(obj, value)
            obj.shadow_x = value;
            obj.shadow_minus_x = -value;
     end
    
     function value = get.x(obj)
          value = obj.shadow_x;
     end
    

    请注意,我没有正确测试这个,所以我不知道 Matlab 中的所有含义。在我熟悉的其他语言中,这应该可以正常工作。

  • 关于警告 - 我的方法是禁用警告是安全的,只要你真的知道你在做什么。
于 2013-08-24T16:41:44.853 回答
1

正如@bavaza所建议的,实现这一点的一种方法是使用具有相应影子私有属性的依赖属性。

下面是实现内部数据结构的代码(受这篇文章的启发)。您需要使用组合来使此类的实例成为外部对象的属性:

classdef Model < handle
    properties (Dependent)
        Q
        Qchol
    end
    properties (Access = private)
        Q_
        Qchol_
    end

    methods
        function obj = Model()
        end

        function val = get.Q(obj)
            val = obj.Q_;
        end
        function val = get.Qchol(obj)
            val = obj.Qchol_;
        end

        function set.Q(obj, val)
            obj.Q_ = val;
            obj.Qchol_ = cholcov(val);
        end
        function set.Qchol(obj, val)
            obj.Qchol_ = val;
            obj.Q_ = val'*val;
        end
    end
end

使用公开的依赖属性设置一个值会影响两个基础变量:

>> m = Model
m = 
  Model with properties:

        Q: []
    Qchol: []

>> m.Qchol = rand(3)
m = 
  Model with properties:

        Q: [3x3 double]
    Qchol: [3x3 double]
于 2013-08-25T21:12:45.317 回答