我在使用点表示法应用方法后尝试引用对象属性时遇到问题。 它只发生在我尝试索引初始对象
时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]
任何想法?
答案 0 :(得分:14)
我肯定会在解析器中将其称为错误;一个错误,因为它没有引发错误,而是允许您首先编写:obj.method.prop
!
MATLAB在这种语法的某些变体中崩溃的事实是一个严重的错误,绝对应该是reported到MathWorks。
现在MATLAB中的一般规则是你不应该直接“索引到结果”。相反,您应该首先将结果保存到变量中,然后索引到该变量。
如果您使用func(obj)
而不是obj.func()
来调用对象的成员方法(dot-notation vs. function notation),那么这一事实很清楚:
>> 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)
(即没有参数的调用函数,然后使用线性索引将结果矩阵索引到第4个元素)f(4)
(调用函数,其中一个参数为n = 4,并返回矩阵magic(4)
)这种混淆是由MATLAB语法中的几个原因引起的:
它允许仅通过名称调用无参数的函数,而不需要括号。如果有f.m
函数,您可以将其称为f
或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如何处理这种情况。
对于那些感兴趣的人,这让我想起了关于包和类的另一个similar bug,并直接索引获取属性。无论是从命令提示符,脚本还是M文件函数调用它,结果都是不同的......