在Matlab中,我想要一个看起来像这样的数据结构:
DataStruct
.model
.Q
.Qchol
.
.
.system
.
.
结构可能是一个类,虽然我并不真正需要oop所有的其他功能。
但我需要
Q
分配了某些内容,则会自动Qchol = cholcov(Q)
。Qchol
分配了某些内容,则会自动Q = Qchol' * Qchol
。Q
和Qchol
都会被存储以便快速读取访问Q
和Qchol
可以通过简单的作业写入,例如:DS1.mod.Q = value
我知道我可以让model
成为一个类,并为Q和Qchol设置/获取方法。然而,对于两个矩阵(加上可能还有更多的字段)来说,这似乎有点过分。另外Matlab 警告我在set方法中不应该访问其他属性。
那么:拥有这样的数据结构的最佳方式是什么,最好没有警告?
答案 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和/或您的计算机。
此时我认为你有两个选择:
Q
或Qchol
设为dependent property。这将以每次读取它时重新计算相关属性为代价。使用一些私有阴影属性,例如shadow_Q
和shadow_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]