Matlab面向对象编程 - 重载size()函数

3
我想在我的一个类中重载size()函数,使其不返回对象的大小,而是返回特定成员的大小。问题是Matlab在类构造函数中调用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()函数来获取对象的大小,但是带上'mv'参数会失去这个函数重载的意义,因为我希望像处理其他对象一样调用size()函数。

有什么建议吗?


你尝试过使用依赖属性吗?声明一个依赖属性,SetAccess = private,名为 size ... - scmg
1个回答

5
如果你想要重载类的 size 方法,那你需要非常小心。这不仅在实现时需要小心,而且在设计类的行为时也需要小心。
首先,请注意是否希望能够创建 dataClass 对象的数组,或者是否只允许创建标量 dataClass 对象。如果你想要创建 dataClass 对象的数组,当传入一个数组时,size 应该返回数组的大小还是每个 dataClass 中数据的大小?是哪个 dataClass 的大小?在标量和数组上调用 size 时,行为是否应该有所不同?这样很容易混乱。
因此,我建议如果你想要重载 size 方法,最好限制你的类只能使用标量。你可以通过重载 cathorzcatvertcat 来实现,并在正确的情况下进行错误处理。
此外,你还需要小心确保不仅重载了 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

如果你按照之前的建议也对cathorzcatvertcatnumel进行了重载,我认为这可以实现你所要求的功能。
但是,还有一件事要注意。你提到MATLAB在对象构造函数中调用size来确定其大小,实际上并不是这样的。发生的情况是,在构造对象后,MATLAB会将结果显示在命令行和控制台,并调用disp方法进行显示,该方法然后调用size来确定大小。它会将其报告为100x100的dataClass数组,这并不是实际情况 - 它是一个1x1的数组,具有一个100x100的memberVar成员变量。您可以通过尝试访问a(2)来测试此情况,这会导致错误。
因此,您还需要重载类的显示方法。您可以通过将类从matlab.mixin.CustomDisplay继承,或者直接重载disp和/或display方法来完成此操作。使它们显示您想要的任何内容,例如memberVar的内容。
最后,请注意:在工作区浏览器中,a被报告为100x100 - 这再次是size的输出。我希望你能接受这一点,因为我不知道有什么方法可以让size向命令行报告一个结果,并向工作区浏览器报告另一个结果。
希望这可以帮到您 - 如您所见,重载size时需要考虑很多事情,这就是为什么它通常不被推荐的原因。

非常感谢,我之前并不知道是disp和工作区浏览器造成了混淆。实际上,我想要的是这个类的数组,尽管只有一维...所以我使用numel确定数组的大小,使用size确定成员变量的大小。重要的是这两个函数能够正常工作,并且它们似乎按照我想要的方式工作。 - phausamann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接