Does MATLAB support "callable" (i.e. function-like) classes? - oop

Is it possible to define a MATLAB class such that the objects from this class can be called like any other function?
IOW, I'm asking whether one can write in MATLAB the equivalent of something like the following Python class:
# 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!

I do not know, whether MATLAB directly supports what you want, but MATLAB does support first-class functions; closures might therefore provide a useable substitute, for instance:
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 over calls (and msg). That way you can express functions that depend on some internal state. You would use it this way:
g = count_call('number of calls: ') % returns a new function ("__init__")
g() % "__call__"

I will be interested to see if this is possible without simply 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 my knowledge goes, if you tried to override the call function you'd run into a conflict with Matlab's parenthetical subscript reference subsref. You can find a reference here showing how to overwrite that, and you might be able to get it to do what you want...but it doesn't seem like good form to do so. Not sure how Matlab would handle a call to an object (as opposed to a function) without it getting confused with this.

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
This would 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 could redefine the subsref function 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 could 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 overriding the subsref or subsasgn functions. They are used for too many cases, and its sometimes hard to get them write. For example all the following will eventually call the subsref method with different input:
f(..)
f.template
f.template(..)
f(..).template
f(..).template(..)
There is also the case of the end keyword which could appear in indexing, so you might have to also override it as well in some cases. Not to mention that objects can also be concatenated into arrays, which makes things even more complicated:
>> ff = [f,f];
>> ff(1) % not what you expect!
That said, I think #Frank's suggestion to use nested functions with closures is more elegant in this case:
function f = FxnClass(t)
f = #call;
function out = call(varargin)
out = sprintf(t, varargin{:});
end
end
which is called as before:
>> f = FxnClass('x = %f, y = %s, z = %d');
>> f(3, 'two', false)

If you mean that you want a class to hold a method which you use like a normal function (eg. defined in an m-file), then yes, Matlab does support static methods.
A static method runs independently of any instances of that class, in fact, you don't even need to instantiate a class to use its static methods.
Matlab does not support static fields, however, so you would have to instantiate such a class first, and then set its fields before using the functions (which presumably make use of these fields, since you are asking this question).
Given the limitation with static members, you might be better off with closures, as described by Frank.

Related

Graceful way to make tables act like values when __indexed?

I'm having this particular problem with my homebrew OO design:
Entity = {}
function Entity:new(o)
o = o or {}
return setmetatable(o, {__index = Entity})
end
function Entity:init() end
function Entity:think() end
function Entity:spawn()
--put in entity pool and begin drawing/logic
self:init()
end
Block = Entity:new{
x = 0,
y = 0,
color = {255, 255, 255, 255},
}
function Block:getPos()
return self.x, self.y
end
--setPos, getColor, setColor etc
function Block:init()
self:setColor(math.random(255), math.random(255), math.random(255))
end
a = Block:new()
a:spawn() --a new block with a random color
--a few seconds later...
b = Block:new()
b:spawn() --all blocks change to new color
The color table is being shared by all prototypes and instances. How can I make that table behave like, say, a string:
a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, table
As opposed to an object:
a = {table}
b = a
print(b[1]) -->table
a[1] = "object"
print(a[1], b[1]) -->object, object
TL;DR: I need to make a new datatype.
There are three ways to fix your problem:
Initialize the Entity.color table during Entity object initialization – put it in Entity:new() function.
Replace the Entity.color table with four variables that will represent its contents – Entity.colorred, Entity.colorgreen, Entity.colorblue, Entity.coloralpha.
Make Entity:setColor() create a new self.color table with new values, instead of modifying the values directly. self.color = {red, green, blue, alpha} instead of self.color[1] = red; self.color[2] = green; self.color[3] = blue; self.color[4] = alpha.
How can I make that table behave like, say, a string:
Your example involves changing Lua variable assignment to copying values rather than references. Even if you could affect such a change in Lua (you can't) it would be an unspeakably terrible idea.
The color table is being shared by all prototypes and instances.
Becase you put it in the prototype (e.g. the "class"), so it's equivalent to a static member in an OOP language, shared by all instances. If you want it to be an instance variable, then it needs to be part of instance construction, not class construction. You need to do the same for x and y as well, or they'll also be shared by all Block instances.
function Block:new()
local instance = { x = 0, y = 0 }
instance:setColor(math.random(255), math.random(255), math.random(255))
return setmetatable(instance, {__index = self})
end
There are enhancements you can make to the constructor, such as passing in parameters (e.g. to initialize x, y, etc.), but the important part is that the instance carries its own state.
Having Entity:spawn simply call init on itself makes no sense. The example code you show suggests it should actually be spawning new instances, but the implementation does not do that.

Why can't I use builtin for classes that overload subsref?

I would like to overload only one type of subsref calls (the '()' type) for a particular class and leave any other calls to Matlab's built in subsref -- specifically, I want Matlab to handle property/method access via the '.' type. But, it seems like Matlab's 'builtin' function doesn't work when subsref is overloaded in a class.
Consider this class:
classdef TestBuiltIn
properties
testprop = 'This is the built in method';
end
methods
function v = subsref(this, s)
disp('This is the overloaded method');
end
end
end
To use the overloaded subsref method, I do this:
t = TestBuiltIn;
t.testprop
>> This is the overloaded method
That's as expected. But now I want to call Matlab's built in subsref method. To make sure I'm doing things right, first I try out a similar call on a struct:
x.testprop = 'Accessed correctly';
s.type = '.';
s.subs = 'testprop';
builtin('subsref', x, s)
>> Accessed correctly
That's as expected as well. But, when I try the same method on TestBuiltIn:
builtin('subsref', t, s)
>> This is the overloaded method
...Matlab calls the overloaded method rather than the built in method. Why does Matlab call the overloaded method when I requested that it call the builtin method?
UPDATE:
In response to #Andrew Janke's answer, that solution almost works but doesn't quite. Consider this class:
classdef TestIndexing
properties
prop1
child
end
methods
function this = TestIndexing(n)
if nargin==0
n = 1;
end
this.prop1 = n;
if n<2
this.child = TestIndexing(n+1);
else
this.child = ['child on instance ' num2str(n)];
end
end
function v = subsref(this, s)
if strcmp(s(1).type, '()')
v = 'overloaded method';
else
v = builtin('subsref', this, s);
end
end
end
end
All of this works:
t = TestIndexing;
t(1)
>> overloaded method
t.prop1
>> 1
t.child
>> [TestIndexing instance]
t.child.prop1
>> 2
But this doesn't work; it uses the built in subsref for the child rather than the overloaded subsref:
t.child(1)
>> [TestIndexing instance]
Note that the above behavior is inconsistent with both of these behaviors (which are as expected):
tc = t.child;
tc(1)
>> overloaded method
x.child = t.child;
x.child(1)
>> overloaded method
It's possible, IIRC. To change () but not {} and '.', write your subsref method to pass those other cases along to the builtin subsref from within your overloaded subsref, instead of trying to explicitly call the builtin from outside.
function B = subsref(A, S)
% Handle the first indexing on your obj itself
switch S(1).type
case '()'
B = % ... do your custom "()" behavior ...
otherwise
% Enable normal "." and "{}" behavior
B = builtin('subsref', A, S(1))
end
end
% Handle "chaining" (not sure this part is fully correct; it is tricky)
orig_B = B; % hold on to a copy for debugging purposes
if numel(S) > 1
B = subsref(B, S(2:end)); % regular call, not "builtin", to support overrides
end
end
(And if that builtin call doesn't work, you can just put in cases that use . and {} directly, because the subsref overload is ignored inside the class definition.)
To make it fully functional, you may need to change B to a varargout, and add chaining behavior in to the "()" case.
To expand on the explanation given on the Mathworks board, builtin only works from within an overloaded method to access the pre-existing (built in) method.
Overloading a method in Matlab effectively shadows the built in implementation from everything except the method doing the shadowing, and the method doing the shadowing must use builtin to access the built in implementation instead of recursing into itself.
In general. You should use builtin(m,s) inside the function that is been overloaded. This is specified clearly in MATLAB documentation.
http://www.mathworks.com/help/matlab/ref/builtin.html
builtin(function,x1,...,xn) executes the built-in function with the
input arguments x1 through xn. Use builtin to execute the original
built-in from within a method that overloads the function. To work
properly, you must never overload builtin.
Consider this code:
classdef TestBuiltIn
properties
testprop = 'This is the built in method';
testprop2 = 'This is the derived subsref ';
end
methods
function v = subsref(m, s)
disp('enter subsref no matter how!');
v = builtin('subsref',m, s);
end
end
end
and test command
clear;
t = TestBuiltIn;
builtin('subsref', t, s)
s.type = '.';
s.subs = 'testprop';
s2 = s;
s2.subs = 'testprop2';
>> builtin('subsref', t, s1)
enter subsref no matter how!
ans =
This is the derived subsref
>> builtin('subsref', t, s)
enter subsref no matter how!
ans =
This is the built in method
In your updated version of this problem, when you call t.child(1), the subsref function will receive argument s with s(1).type='.', s(1).subs='child' and s(2).type='()', s(2).subs='1'. The evaluation of this expression is not in a step-by-step manner, as Andrew Janke mentioned in his answer. As a result, when overriding subsref, you should handle this operation chain, by first processing the '.' operator. Here is a incomplete example for your case,
function v = subsref(this, s)
switch s(1).type
case '.'
member = s(1).subs;
if ismethod(this, member)
% invoke builtin function to access method member
% there is issue about the number of output arguments
v = builtin('subsref',this,s);
elseif isprop(this, member) % property
if length(s) == 1
% invoke builtin function to access method member
v = builtin('subsref', this, s);
elseif length(s) == 2 && strcmp(s(2).type,'()')
% this is where you evaluate 'tc.child(1)'
else
% add other cases when you need, otherwise calling builtin
end
else
% handling error.
end
case '()'
% this is where you evaluate 't(1)'
% you may need to handle something like 't(1).prop1', like the '.' case
otherwise
% by default, calling the builtin.
end
end
You can also find a detailed code sample and instruction at Code Patterns for subsref and subsasgn Methods.
One more thing you may need to know, is that method members in this class will also be invoked through subsref with '.' operation. Look at this subject subsref on classes: how to dispatch methods?, you will find that the builtin function has no return value (since the invoked method has no return value). However, the return value of builtin is assigned to v(even though v is replaced by varargout), which is an obvious error. The author also gives a temporary solution by using try ... catch to resolve this error.

MATLAB - how to use event.eventData, and efficiently

For background information and context for my question, please read this question.
Notice in the updatePlot() method of my DynamicPlotter code, I kind of "reach into" a DynamicDataset property, as follows:
function updatePlot(obj, propNum)
X = get(obj.LH(propNum), 'XData');
Y = get(obj.LH(propNum), 'YData');
X(end+1) = obj.(dynProps{propNum}).newestData(1);
Y(end+1) = obj.(dynProps{propNum}).newestData(2);
set(obj.LH(propNum), 'XData', X, 'YData', Y);
end
updatePlot is a listener callback. Rather than "reach in" to go get the newestData, I am wondering if it would be more efficient to have the data "presented" to the callback with event.eventData. But I am unsure of (a) how to even use event.eventData (the example provided in the documentation isn't very clear to me), and (b) if this yields better or worse performance.
So I guess my main question is, what's the best way for updatePlot() to access the newestData as depicted in the method above: "reaching in and retrieving it" or using event.eventData to "send" the data point to the function to plot?
I hope this wasn't terribly ambiguous.
You first need to have a class that defines an event (in MyClass.m):
classdef MyClass < handle
events
% Event
MyEvent
end
methods
function obj = MyClass
% Constructor
end
end
end
Then you need to create your own EventData subclass (in MyEventData.m):
classdef MyEventData < event.EventData
properties (Access = public)
% Event data
Data
end
methods
function this = MyEventData(data)
% Constructor
this.Data = data;
end
end
end
Attach your data to an instance of the event data class (in a script file):
X = 1:10;
Y = 1:10;
data = struct('XData', X, 'YData', Y);
eventData = MyEventData(data);
And fire the event from your obj and have a listener listen to it:
obj = MyClass;
l = addlistener(obj, 'MyEvent', #(evtSrc,evtData)disp(evtData.Data));
notify(obj, 'MyEvent', eventData)
Anytime you call notify(...), the evtData argument in your listener callback will have your data in its Data property:
>> notify(obj, 'MyEvent', eventData)
XData: [1 2 3 4 5 6 7 8 9 10]
YData: [1 2 3 4 5 6 7 8 9 10]

MATLAB - Dependent properties and calculation

Suppose I have the following class which calculates the solution to the quadratic equation:
classdef MyClass < handle
properties
a
b
c
end
properties (Dependent = true)
x
end
methods
function x = get.x(obj)
discriminant = sqrt(obj.b^2 - 4*obj.a*obj.c);
x(1) = (-obj.b + discriminant)/(2*obj.a);
x(2) = (-obj.b - discriminant)/(2*obj.a);
end
end
end
Now suppose I run the following commands:
>>quadcalc = MyClass;
>>quadcalc.a = 1;
>>quadcalc.b = 4;
>>quadcalc.c = 4;
At this point, quadcalc.x = [-2 -2]. Suppose I call quadcalc.x multiple times without adjusting the other properties, i.e., quadcalc.x = [-2 -2] every single time I ask for this property. Is quadcalc.x recalculated every single time, or will it just "remember" [-2 -2]?
Yes, x is recalculated every single time. This is kind of the point of having a dependent property, since it guarantees that the result in x is always up to date.
If you want to make x a "lazy dependent property", you may want to look at the suggestions in my answer to this question.

Quick-and-dirty class constructor for MATLAB?

I am trying to make MATLAB a bit more usable than it is (for me), and one of the things which I always wanted to fix is a better class constructor. I want to have the following interface:
MyClass.new(some_args).method1;
# instead of classical:
obj = MyClass(some_args);
obj.method1;
I can easily achieve this by defining a static method new:
classdef MyClass
methods
function obj = MyClass(varargin); end
function method1(obj,varargin); end
end
methods (Static)
function obj = new(varargin); obj = MyClass(varargin{:}); end
end
end
But this requires adding such method to all classes, and therefore it is not very elegant/convenient. I thought that I could go around it by defining a common class with the following constructor
classdef CommonClass
methods (Static)
function obj = new(varargin)
# getting name of the current file (Object), i.e. basename(__FILE__)
try clear E; E; catch E, [s, s] = fileparts(E.stack(1).file); end;
# creating object with name $s
obj = eval([s '(varargin{:})']);
end
end
end
classdef MyClass < CommonClass
end
However, this doesn't work because MATLAB calls new() from Object.m, and therefore I get instance of Object instead of MyClass.
Any ideas how I can improve it?
EDIT1:
I would like it to work also for classes created inside other ones:
classdef MyAnotherClass < CommonClass
methods
function obj = MyAnotherClass
child = MyClass.new;
end
end
end
>> MyAnotherClass.new
Personally, I don't see the problem with calling the constructor as is, but if you do want to have it called via new, the getStaticCallingClassName below might be of use to you.
Here's how you'd use it:
classdef CommonClass
methods (Static)
function obj = new(varargin)
%# find out which class we have to create
className = getStaticCallingClassName;
constructor = str2func(sprintf('#%s'className));
%# creating object with name $s
obj = constructor(varargin{:});
end
end
end
classdef MyClass < CommonClass
end
With this, you can call
obj = MyClass.new(input,arguments);
And here's getStaticCallingClassName:
function className = getStaticCallingClassName
%GETSTATICCALLINGCLASSNAME finds the classname used when invoking an (inherited) static method.
%
% SYNOPSIS: className = getStaticCallingClassName
%
% INPUT none
%
% OUTPUT className: name of class that was used to invoke an (inherited) static method
%
% EXAMPLE
%
% Assume you define a static method in a superclass
% classdef super < handle
% methods (Static)
% doSomething
% % do something here
% end
% end
% end
%
% Also, you define two subclasses
% classdef sub1 < super
% end
%
% classdef sub2 < super
% end
%
% Both subclasses inherit the static method. However, you may be
% interested in knowing which subclass was used when calling the static
% method. If you call the subclass programmatically, you can easily pass
% the name of the subclass as an input argument, but you may want to be
% able to call the method from command line without any input and still
% know the class name.
% getStaticCallingClassName solves this problem. Calling it in the above
% static method 'doSomething', it returns 'sub1' if the static method was
% invoked as sub1.doSomething. It also works if you create an instance of
% the subclass first, and then invoke the static method from the object
% (e.g. sc = sub1; sc.doSomething returns 'sub1' if .doSomething calls
% getStaticCallingClassName)
%
% NOTE: getStaticCallingClassName reads the last workspace command from
% history. This is an undocumented feature. Thus,
% getStaticCallingClassName may not work in future releases.
%
% created with MATLAB ver.: 7.9.0.3470 (R2009b) on Mac OS X Version: 10.5.7 Build: 9J61
%
% created by: Jonas Dorn
% DATE: 16-Jun-2009
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% get the last entry of the command line from the command history
javaHistory=com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory;
lastCommand = javaHistory(end).toCharArray';%'# SO formatting
% find string before the last dot.
tmp = regexp(lastCommand,'(?:=|\.)?(\w+)\.\w+\(?(?:.*)[;,]*\s*$','tokens');
try
className = tmp{1}{1};
catch me
className = [];
end
% if you assign an object, and then call the static method from the
% instance, the above regexp returns the variable name. We can get the
% className through getting the class of xx.empty.
if ~isempty(className)
className = evalin('base',sprintf('class(%s.empty);',className));
end
I could be missing something, but what's wrong with
method1(MyClass(some_args))
? (I use this pattern all the time).