Does MATLAB support "callable" (i.e. Functional) classes?

Is it possible to define the MATLAB class so that objects of this class can be called like any other function?

IOW, I ask if it is possible to write the equivalent of the following Python class in MATLAB:

# define the class FxnClass class FxnClass(object): def __init__(self, template): self.template = template def __call__(self, x, y, z): print self.template % locals() # create an instance of FxnClass f = FxnClass('x is %(x)r; y is %(y)r; z is %(z)r') # call the instance of FxnClass f(3, 'two', False) ... [OUTPUT] x is 3; y is 'two'; z is False 

Thanks!

+4
source share
4 answers

I will be interested to know if this is possible simply without creating a Java method in Matlab. I know you can do the following

 classdef ExampleObject properties test; end methods function exampleObject = ExampleObject(inputTest) exampleObject.test=inputTest; end function f(exampleObject,funcInput) disp(funcInput+exampleObject.test); end end end >> e=ExampleObject(5); >> f(e,10) 15 

But as far as I know, if you tried to override the call function, you would subsref into a conflict with the link in parentheses in the Matlab subsref table. Here you can find a link that shows how to rewrite it, and you can get it to do what you want ... but it’s not. For me it looks like a good form. Not sure how Matlab will handle an object call (as opposed to a function) without getting confused with this.

+4
source

I don't know if MATLAB supports what you want, but MATLAB supports first-class functions; Thus, closures may be suitable for use, for example:

 function f = count_call(msg) calls = 0; function current_count() disp(strcat(msg, num2str(calls))); calls = calls + 1; end f = @current_count; end 

In this case, current_count closes above calls (and msg ). Thus, you can express functions that depend on some internal state. You would use it like this:

 g = count_call('number of calls: ') % returns a new function ("__init__") g() % "__call__" 
+5
source

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) 
+4
source

If you want the class to hold a method that you use as a regular function (for example, defined in the m file), then yes, Matlab supports static methods .

The static method works regardless of any instances of this class; in fact, you don’t even need to instantiate the class to use its static methods.

Matlab does not support static fields , so you first need to instantiate such a class, and then set its fields before using functions (which presumably make use of these fields as you ask this question).

Given the limitation with static members, you might be better off with a closure, as described by Frank .

+1
source

All Articles