MATLAB:varargin 与 'real' 元胞数组的行为不同?
MATLAB: varargin acting differently from 'real' cell array?
varargin 与元胞数组完全一样吗?
我的测试中有一个简单的 varargin 解析器 class 如下所示:
classdef MySuperClass
properties(Access = protected)
superPropA = (1:4);
superPropB = 'superBar';
end
methods
% constructor
function obj = MySuperClass(varargin)
% check varargins
% required parameter
arg = varargin(find(strcmp(varargin, 'SuperA'))+1);
if ~isempty(arg) && isnumeric(arg{1}) && length(arg{1}) > 1
obj.superPropA = arg{1};
else
newExc = MException('SubClass:Constructor:InputParser',...
'Expected numeric vector argument for SuperA');
throw(newExc);
end
% optional parameter
if any(strcmp(varargin, 'SuperB'))
arg = varargin(find(strcmp(varargin, 'SuperB'))+1);
if ~isempty(arg)
obj.superPropB = arg{1};
else
newExc = MException('SubClass:Constructor:InputParser',...
'Expected argument for SuperB');
throw(newExc);
end
end
% output varargins
fprintf('SuperClass:\nSuper property A: %s\nSuper property B: %s', obj.superPropA, obj.superPropB);
end
end
end
当我用子 class
中的 SubInst = MySubClass('SuperA', (1:5), 'SuperB', 'Hello')
实例化 class 时
function obj = MySubClass(varargin)
% call super class constructor
obj = obj@SuperClassModules.MySuperClass(varargin);
...
用解析器调用 superclass 的构造函数,然后 arg 是 {}(见第一个代码块),根据我的理解,这不应该。
因为当我在控制台输入:
>> a = {'SuperA', (1:5), 'SuperB', 'Hello'}
a =
'SuperA' [1x5 double] 'SuperB' 'Hello'
>> arg = a(find(strcmp(a, 'SuperA'))+1)
arg =
[1x5 double]
>> arg{1}
ans =
1 2 3 4 5
它按预期工作。
为什么它在构造函数内部不起作用?
为简化起见,我在解释问题时会忘记所有 class 内容。你有一个函数 foo(varargin)
和 bar(varargin)
如果您现在调用 foo(1,2,3)
,它会被调用 varargin={1,2,3}
。如果你现在想在 foo
中调用 bar(1,2,3)
,你不能简单地使用 bar(varargin)
,那就是 bar({1,2,3})
。相反,您必须使用逗号分隔列表调用 bar
:bar(varargin{:})
。这会将元胞数组的元素解压缩为 1,2,3
,从而产生您想要的调用。
在您的代码中它将是:
obj = obj@SuperClassModules.MySuperClass(varargin{:});
varargin 与元胞数组完全一样吗?
我的测试中有一个简单的 varargin 解析器 class 如下所示:
classdef MySuperClass
properties(Access = protected)
superPropA = (1:4);
superPropB = 'superBar';
end
methods
% constructor
function obj = MySuperClass(varargin)
% check varargins
% required parameter
arg = varargin(find(strcmp(varargin, 'SuperA'))+1);
if ~isempty(arg) && isnumeric(arg{1}) && length(arg{1}) > 1
obj.superPropA = arg{1};
else
newExc = MException('SubClass:Constructor:InputParser',...
'Expected numeric vector argument for SuperA');
throw(newExc);
end
% optional parameter
if any(strcmp(varargin, 'SuperB'))
arg = varargin(find(strcmp(varargin, 'SuperB'))+1);
if ~isempty(arg)
obj.superPropB = arg{1};
else
newExc = MException('SubClass:Constructor:InputParser',...
'Expected argument for SuperB');
throw(newExc);
end
end
% output varargins
fprintf('SuperClass:\nSuper property A: %s\nSuper property B: %s', obj.superPropA, obj.superPropB);
end
end
end
当我用子 class
中的SubInst = MySubClass('SuperA', (1:5), 'SuperB', 'Hello')
实例化 class 时
function obj = MySubClass(varargin)
% call super class constructor
obj = obj@SuperClassModules.MySuperClass(varargin);
...
用解析器调用 superclass 的构造函数,然后 arg 是 {}(见第一个代码块),根据我的理解,这不应该。
因为当我在控制台输入:
>> a = {'SuperA', (1:5), 'SuperB', 'Hello'}
a =
'SuperA' [1x5 double] 'SuperB' 'Hello'
>> arg = a(find(strcmp(a, 'SuperA'))+1)
arg =
[1x5 double]
>> arg{1}
ans =
1 2 3 4 5
它按预期工作。
为什么它在构造函数内部不起作用?
为简化起见,我在解释问题时会忘记所有 class 内容。你有一个函数 foo(varargin)
和 bar(varargin)
如果您现在调用 foo(1,2,3)
,它会被调用 varargin={1,2,3}
。如果你现在想在 foo
中调用 bar(1,2,3)
,你不能简单地使用 bar(varargin)
,那就是 bar({1,2,3})
。相反,您必须使用逗号分隔列表调用 bar
:bar(varargin{:})
。这会将元胞数组的元素解压缩为 1,2,3
,从而产生您想要的调用。
在您的代码中它将是:
obj = obj@SuperClassModules.MySuperClass(varargin{:});