One way is to override the feval function for your class:
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
It will be used as:
>> f = FxnClass('x = %f, y = %s, z = %d'); >> feval(f, 3,'two',false) ans = x = 3.000000, y = two, z = 0
Now, if you want to provide additional syntactic sugar , you can redefine subsref for your class as @Salain suggested. Add the following to the previous class definition:
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
Now you can simply write:
>> f = FxnClass('x = %f, y = %s, z = %d'); >> f(3,'two',false) ans = x = 3.000000, y = two, z = 0
Personally, I donβt particularly like redefining the functions of subsref or subsasgn . They are used for too many occasions and are sometimes difficult to get to write. For example, all subsequent calls will call the subsref method with a different input:
f(..) f.template f.template(..) f(..).template f(..).template(..)
There is also an end keyword that may appear during indexing, so in some cases you will also have to override it. Not to mention that objects can also be combined into arrays, which makes things even more complex:
>> ff = [f,f]; >> ff(1) % not what you expect!
However, I think that @Frank suggests using nested functions with closure in this case more elegantly:
function f = FxnClass(t) f = @call; function out = call(varargin) out = sprintf(t, varargin{:}); end end
which is still called:
>> f = FxnClass('x = %f, y = %s, z = %d'); >> f(3, 'two', false)