Matlab OOP - 重载大小()
Matlab OOP - Overloading size()
我想为我的 class 之一重载 size()
函数,这样它就不会 return 对象的大小,而是特定成员的大小。问题是 Matlab 在 class 构造函数中调用 obj.size 以确定对象数组的大小。
例如:
classdef dataClass < handle
properties
memberVar
end
methods
function obj = dataClass(mvIn)
if nargin ~= 0
if ~ismatrix(mvIn)
error('Input must be a matrix');
end
obj.memberVar = mvIn;
end
end
function sz = size(obj, varargin)
h = @(x)builtin('size', x, varargin{:});
sz = cell2mat(cellfun(h, {obj.memberVar}', 'uni', 0));
end
end
end
不起作用,因为对象数组的大小与 memberVar
的大小相同
a = dataClass(ones(100))
a =
100x100 dataClass array with properties:
memberVar: [100x100 double]
解决方法是将重载实现为
function sz = size(obj, varargin)
idx = strcmpi(varargin, 'mv');
if any(idx)
varargin = varargin(~idx);
h = @(x)builtin('size', x, varargin{:});
sz = cell2mat(cellfun(h, {obj.memberVar}', 'uni', 0));
else
sz = builtin('size', obj, varargin{:});
end
end
并调用 size(obj, 'mv')
但这违背了重载的全部目的,因为我想像调用任何其他对象一样调用 size()
。
有什么建议吗?
如果要为 class 重载 size
,则需要格外小心 - 这既要小心实现事物的方式,也要小心设计你想要的 class 行为举止。
首先,请注意,您需要决定是否能够为 dataClass
对象制作数组,或者您是否愿意只制作标量 dataClass
对象。如果您希望能够创建 dataClass
对象的数组,那么当给定这样一个数组时,您究竟希望 size
做什么?你想让它报告数组的大小,还是一个 dataClass
内的数据大小?哪个dataClass
?您是否希望它在标量和数组上调用时切换行为?这很快就会让人感到困惑。
所以首先,我建议如果你想超载 size
,你可能想要限制你的 class,这样就不可能使用标量以外的任何东西.您可以通过重载 cat
、horzcat
和 vertcat
并让它们出错(小心,在完全正确的情况下)来做到这一点。
除此之外,您需要小心确保不仅 size
过载,而且 numel
也过载。 size
和 numel
以一些不明显的方式相互作用。
话虽如此,您应该能够实现如下内容:
classdef dataClass < handle
properties
memberVar
end
methods
function obj = dataClass(mvIn)
if nargin ~= 0
if ~ismatrix(mvIn)
error('Input must be a matrix');
end
obj.memberVar = mvIn;
end
end
function sz = size(obj, varargin)
sz = builtin('size', obj.memberVar, varargin{:});
end
end
end
如果您还按照上面的建议重载了 cat
、horzcat
、vertcat
和 numel
,我认为这可以满足您的要求。
不过,还有一点需要注意。您提到 MATLAB 在对象构造函数中调用 size
来确定其大小。实际情况并非如此 - 实际情况是,在您构造它之后,MATLAB 在命令行显示结果并调用 disp
,然后调用 size
来确定大小。它将它报告为 dataClass
的 100x100 数组,但事实并非如此 - 它是具有 100x100 memberVar
的 1x1 数组。您可以通过尝试访问 a(2)
来测试它,这将出错。
所以你也然后需要重载class的显示方法。您可以通过从 matlab.mixin.CustomDisplay
继承 class 或直接重载方法 disp
and/or display
来做到这一点。让他们显示任何你想要的,比如 memberVar
.
的内容
请注意最后一件事:在工作区浏览器中,a 被报告为 100x100 - 这又是 size
的输出。我希望您对此表示满意,因为据我所知,无法让大小向命令行报告一件事,而向工作区浏览器报告另一件事。
希望对您有所帮助 - 如您所见,重载 size
时需要考虑很多因素,这就是为什么通常不推荐这样做的原因。
我想为我的 class 之一重载 size()
函数,这样它就不会 return 对象的大小,而是特定成员的大小。问题是 Matlab 在 class 构造函数中调用 obj.size 以确定对象数组的大小。
例如:
classdef dataClass < handle
properties
memberVar
end
methods
function obj = dataClass(mvIn)
if nargin ~= 0
if ~ismatrix(mvIn)
error('Input must be a matrix');
end
obj.memberVar = mvIn;
end
end
function sz = size(obj, varargin)
h = @(x)builtin('size', x, varargin{:});
sz = cell2mat(cellfun(h, {obj.memberVar}', 'uni', 0));
end
end
end
不起作用,因为对象数组的大小与 memberVar
的大小相同a = dataClass(ones(100))
a =
100x100 dataClass array with properties:
memberVar: [100x100 double]
解决方法是将重载实现为
function sz = size(obj, varargin)
idx = strcmpi(varargin, 'mv');
if any(idx)
varargin = varargin(~idx);
h = @(x)builtin('size', x, varargin{:});
sz = cell2mat(cellfun(h, {obj.memberVar}', 'uni', 0));
else
sz = builtin('size', obj, varargin{:});
end
end
并调用 size(obj, 'mv')
但这违背了重载的全部目的,因为我想像调用任何其他对象一样调用 size()
。
有什么建议吗?
如果要为 class 重载 size
,则需要格外小心 - 这既要小心实现事物的方式,也要小心设计你想要的 class 行为举止。
首先,请注意,您需要决定是否能够为 dataClass
对象制作数组,或者您是否愿意只制作标量 dataClass
对象。如果您希望能够创建 dataClass
对象的数组,那么当给定这样一个数组时,您究竟希望 size
做什么?你想让它报告数组的大小,还是一个 dataClass
内的数据大小?哪个dataClass
?您是否希望它在标量和数组上调用时切换行为?这很快就会让人感到困惑。
所以首先,我建议如果你想超载 size
,你可能想要限制你的 class,这样就不可能使用标量以外的任何东西.您可以通过重载 cat
、horzcat
和 vertcat
并让它们出错(小心,在完全正确的情况下)来做到这一点。
除此之外,您需要小心确保不仅 size
过载,而且 numel
也过载。 size
和 numel
以一些不明显的方式相互作用。
话虽如此,您应该能够实现如下内容:
classdef dataClass < handle
properties
memberVar
end
methods
function obj = dataClass(mvIn)
if nargin ~= 0
if ~ismatrix(mvIn)
error('Input must be a matrix');
end
obj.memberVar = mvIn;
end
end
function sz = size(obj, varargin)
sz = builtin('size', obj.memberVar, varargin{:});
end
end
end
如果您还按照上面的建议重载了 cat
、horzcat
、vertcat
和 numel
,我认为这可以满足您的要求。
不过,还有一点需要注意。您提到 MATLAB 在对象构造函数中调用 size
来确定其大小。实际情况并非如此 - 实际情况是,在您构造它之后,MATLAB 在命令行显示结果并调用 disp
,然后调用 size
来确定大小。它将它报告为 dataClass
的 100x100 数组,但事实并非如此 - 它是具有 100x100 memberVar
的 1x1 数组。您可以通过尝试访问 a(2)
来测试它,这将出错。
所以你也然后需要重载class的显示方法。您可以通过从 matlab.mixin.CustomDisplay
继承 class 或直接重载方法 disp
and/or display
来做到这一点。让他们显示任何你想要的,比如 memberVar
.
请注意最后一件事:在工作区浏览器中,a 被报告为 100x100 - 这又是 size
的输出。我希望您对此表示满意,因为据我所知,无法让大小向命令行报告一件事,而向工作区浏览器报告另一件事。
希望对您有所帮助 - 如您所见,重载 size
时需要考虑很多因素,这就是为什么通常不推荐这样做的原因。