有没有办法在MATLAB中“声明”具有特定用户定义类型的变量? zeros()仅适用于内置数值类型。我提出的唯一解决方案是使用repmat()复制虚拟对象零次:
arr = repmat(myClass(), [1 0])
如果不以这种方式声明变量,任何执行“arr(end + 1)= myClass()”的代码都必须包含默认空矩阵的特殊情况,该矩阵的类型为double。
我是否错过了一些更明智的事情?
答案 0 :(得分:6)
根据this documentation,所有类都有一个empty
方法,可以创建该类的空数组。例如:
arr = myClass.empty(0,0); %# Creates a 0-by-0 array of class myClass
也是如此
a = uint8.empty(0,1); %# A 0-by-1 uint8 array
b = single.empty(5,0); %# A 5-by-0 single array
c = cell.empty(0,0); %# A 0-by-0 cell array
您提到过您将通过以下方式在循环中增长此数组:
arr(end+1) = myClass();
如果您知道数组的最终大小,通常在循环外preallocate the entire array更有效,然后覆盖或修改循环中的数组元素。我将讨论如何在an answer to another question中为用户定义的类执行此操作。
答案 1 :(得分:2)
这就是我使用的。您可以使用带有标量大小参数的略微格式。
r = repmat(MyClass, 0);
请注意,您并未声明变量具有类型;它仍然只是具有类型的变量中保存的值。
这适用于旧样式和新MCOS类。如果您正在使用所有新的样式类,gnovice的“empty()”听起来是个好主意。
如果你感觉很高级,还有另一种选择,我将其包括在内以便完整。
您也可以在subasgn中为您的对象处理此问题,至少对于旧式的Matlab类来说。如果在RHS(“右侧”)上使用用户定义的对象对单位化变量进行索引赋值,则会调用该类的subsagn,LHS将以[](空双精度)形式出现。如果你有一个特殊的构造函数表单允许你构造一个空对象而不调用对象上的repmat,你可以支持这个,这样用户就不必使用你的类的对象预先分配它们的变量。
在你的subasgn中:
function obj = subsasgn(obj, S, B)
...
s = S(1);
...
switch s.type
case '()'
% Handle dispatch on LHS autovivification
if isnumeric(obj) && isa(B, mfilename('class'))
% Must use special ctor to preallocate
obj = feval(class(B), mxdims(size(B)));
end
然后在你的构造函数中,通过祝福预先重新组织的结构,有一个后门调用表格来构建空虚。
function MyClass(varargin) %constructor
SuperClasses = { }; % if you inherit, fill this in
if nargin == 1 && isa(varargin{1}, 'mxdims')
% special backdoor to support preallocation without repmat
s = repmat(DataStructure, msize(varargin{1})); % built-in repmat called on plain struct
out = class(s, mfilename, SuperClasses{:});
return;
end
...
@mxdims类是一个特殊的类,您需要创建一个包含大小向量的类,并用作调用此后门表单的标记。 msize()方法返回它代表的大小向量。
如果您定义MyClass以便它支持此功能,那么您可以在不预先分配s的情况下执行“s(1)= MyClass”。但你不能做“s(结束+ 1)”; “end”仅适用于预先分配的值。
这是Matlab工作的一个棘手的领域。在subsasgn和类似系统中工作会产生许多细微的错误,包括段错误。这样做可以为您的用户定义对象提供更“完整”的行为。但它涉及工作和脆弱,你最好坚持使用“repmat( class ,0)”或“empty()”。