一种方法是覆盖feval
类的函数:
classdef FxnClass < handle
properties
template
end
methods
function obj = FxnClass(t)
obj.template = t;
end
function out = feval(obj, varargin)
out = sprintf(obj.template, varargin{:});
end
end
end
这将用作:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> feval(f, 3,'two',false)
ans =
x = 3.000000, y = two, z = 0
现在,如果您想提供额外的语法糖,您可以按照@Salain的建议重新定义subsref
您的课程的功能。将以下内容添加到之前的类定义中:
classdef FxnClass < handle
...
methods
function out = subsref(obj, S)
switch S(1).type
case '.'
% call builtin subsref, so we dont break the dot notation
out = builtin('subsref', obj, S);
case '()'
out = feval(obj, S.subs{:});
case '{}'
error('Not a supported subscripted reference');
end
end
end
end
现在你可以简单地写:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3,'two',false)
ans =
x = 3.000000, y = two, z = 0
就我个人而言,我不是特别喜欢覆盖subsref
orsubsasgn
函数。它们用于太多情况,有时很难让它们写出来。例如,以下所有内容最终都会subsref
使用不同的输入调用该方法:
f(..)
f.template
f.template(..)
f(..).template
f(..).template(..)
还有end
可能出现在索引中的关键字的情况,因此在某些情况下您可能还必须覆盖它。更不用说对象也可以连接成数组,这让事情变得更加复杂:
>> ff = [f,f];
>> ff(1) % not what you expect!
也就是说,我认为@Frank建议在这种情况下使用带有闭包的嵌套函数更优雅:
function f = FxnClass(t)
f = @call;
function out = call(varargin)
out = sprintf(t, varargin{:});
end
end
像以前一样调用:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3, 'two', false)