具有依赖字段的子结构

时间:2013-08-24 15:51:31

标签: matlab oop data-structures

在Matlab中,我想要一个看起来像这样的数据结构:

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

结构可能是一个类,虽然我并不真正需要oop所有的其他功能。

但我需要

  • 如果为Q分配了某些内容,则会自动Qchol = cholcov(Q)
  • 如果为Qchol分配了某些内容,则会自动Q = Qchol' * Qchol
  • 同时,QQchol都会被存储以便快速读取访问
  • QQchol可以通过简单的作业写入,例如:DS1.mod.Q = value

我知道我可以让model成为一个类,并为Q和Qchol设置/获取方法。然而,对于两个矩阵(加上可能还有更多的字段)来说,这似乎有点过分。另外Matlab 警告我在set方法中不应该访问其他属性。

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

2 个答案:

答案 0 :(得分: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和/或您的计算机。

此时我认为你有两个选择:

  • QQchol设为dependent property。这将以每次读取它时重新计算相关属性为代价。
  • 使用一些私有阴影属性,例如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中的所有含义。在我熟悉的其他语言中,这应该可以正常工作。

  • 关于警告 - 我的方法是,只要你真的知道你在做什么,就可以安全地禁用警告。

答案 1 :(得分:1)

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

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

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]