索引对象点表示法给出标量属性

2024-04-08

当我在使用点表示法应用方法后尝试引用对象属性时,我遇到了问题。 仅当我尝试索引初始对象时才会发生

classdef myclassexample

properties
    data
end    

methods   
    function obj = procData(obj)            
        if numel(obj)>1
            for i = 1:numel(obj)
                obj(i) = obj(i).procData;
            end
            return
        end
        %do some processing
        obj.data = abs(obj.data);
    end
end
end

然后分配以下内容

A = myclassexample;
A(1).data= - -1;
A(2).data =  -2;

当调用整个数组并收集属性数据时,它工作正常

[A.procData.data]

如果我尝试索引 A 那么我只能得到一个标量

[A([1 2]).procData.data]

尽管在没有属性调用的情况下看起来效果很好

B  = A([1 2]).procData;
[B.data]

有任何想法吗?


我肯定会称这是解析器中的错误;一个错误,因为它一开始并没有抛出错误,而是允许您编写:obj.method.prop首先!

MATLAB 在该语法的某些变体中崩溃的事实是一个严重的错误,绝对应该解决reported http://www.mathworks.com/support/bugreports/到 MathWorks。

现在 MATLAB 中的一般规则是您不应该直接“索引到结果”。相反,您应该首先将结果保存到变量中,然后索引到该变量中。

如果您使用以下表格,这一事实就很清楚func(obj)而不是obj.func()调用对象的成员方法(点表示法与函数表示法 http://www.mathworks.com/help/matlab/matlab_oop/ordinary-methods.html#brd2n2o-2):

>> A = MyClass;
>> A.procData.data       % or A.procData().data
ans =
     []
>> procData(A).data
Undefined variable "procData" or class "procData". 

相反,正如您所指出的,您应该使用:

>> B = procData(A):    % or: B = A.pocData;
>> [B.data]

FWIW,这也是使用普通结构和常规函数(而不是 OOP 对象和成员函数)时发生的情况,因为无论如何您都无法索引到函数调用的结果。例子:

% a function that works on structure scalar/arrays
function s = procStruct(s)
    if numel(s) > 1
        for i=1:numel(s)
            s(i) = procStruct(s(i));
        end
    else
        s.data = abs(s.data);
    end
end

那么以下所有调用都会抛出错误(正如它们应该的那样):

% 1x2 struct array
>> s = struct('data',{1 -2});

>> procStruct(s).data
Undefined variable "procStruct" or class "procStruct". 

>> procStruct(s([1 2])).data
Undefined variable "procStruct" or class "procStruct". 

>> feval('procStruct',s).data
Undefined variable "feval" or class "feval". 

>> f=@procStruct; f(s([1 2])).data
Improper index matrix reference. 

您可能会问自己为什么他们决定不允许这样的语法。事实证明,MATLAB 不允许对函数调用进行索引(无需引入临时变量)是有充分理由的,无论是点索引还是下标索引。

以下面的函数为例:

function x = f(n)
    if nargin == 0, n=3; end
    x = magic(n);
end

如果我们允许对函数调用进行索引,那么如何解释以下调用就会产生歧义f(4):

  • 是否应该解释为:f()(4)(即不带参数调用函数,然后使用线性索引对结果矩阵进行索引以获得第四个元素)
  • 或者应该解释为:f(4)(调用一个参数为 n=4 的函数,并返回矩阵magic(4))

这种混乱是由 MATLAB 语法中的几个问题引起的:

  • 它允许仅通过名称调用不带参数的函数,而不需要括号。如果有一个函数f.m,你可以将其称为f or f()。这使得解析 M 代码变得更加困难,因为不清楚标记是变量还是函数。

  • 括号用于矩阵索引和函数调用。所以如果一个令牌x代表一个变量,我们使用语法x(1,2)作为矩阵的索引。同时如果x是函数的名称,那么x(1,2)用于调用带有两个参数的函数。

另一个令人困惑的地方是逗号分隔的列表和返回多个输出的函数。例子:

>> [mx,idx] = max(magic(3))
mx =
     8     9     7
idx =
     1     3     2

>> [mx,idx] = max(magic(3))(4)     % now what?

我们应该从 MAX 返回每个输出变量的第 4 个元素,还是仅从第一个输出参数返回第 4 个元素以及完整的第二个输出?当函数返回不同大小的输出时怎么办?

所有这些仍然适用于其他类型的索引:f()(3)/f(3), f().x/f.x, f(){3}/f{3}.

因此,MathWorks 决定避免上述所有混乱,并且不允许直接对结果进行索引。不幸的是,他们限制了这个过程中的语法。例如 Octave 就没有这样的限制(你可以写magic(4)(1,2)),但是话又说回来,新的OOP系统还在开发过程中,所以我不知道Octave如何处理这种情况。


对于那些感兴趣的人来说,这让我想起了另一个类似的错误 https://stackoverflow.com/a/10780871/97160关于包和类以及直接索引以获取属性。无论您是从命令提示符、脚本还是 M 文件函数调用它,结果都是不同的......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

索引对象点表示法给出标量属性 的相关文章

随机推荐