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]
Related
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.
I want to create a subclass, ess say, to the built-in ss class. I'd like to be able to convert an existing ss object to an ess object and at the same time add the missing properties, e.g. w, by something like this
sys=ss(a,b,c,d);
esys=ess(sys,w);
but I can't figure out how to setup the constructor correctly. What is the best way to achieve this? My code currently looks like this
classdef ess < ss
properties
w
end
methods
function obj = ess(varargin)
if nargin>0 && isa(varargin{1},'StateSpaceModel')
super_args{1} = sys;
else
super_args = varargin;
end
obj = obj#ss(super_args{:});
end
end
end
But this does not work as I get the following error:
>> ess(ss(a,b,c,d))
??? When constructing an instance of class 'ess', the constructor must preserve
the class of the returned object.
Of course I could copy all the object properties by hand but it seems to me that there should be some better way.
Here is an example of what I had in mind:
classdef ss < handle
properties
a
b
end
methods
function obj = ss(varargin)
args = {0 0}; %# default values
if nargin > 0, args = varargin; end
obj.a = args{1};
obj.b = args{2};
end
end
end
and:
classdef ess < ss
properties
c
end
methods
function obj = ess(c, varargin)
args = {};
if nargin>1 && isa(varargin{1}, 'ss')
args = getProps(varargin{1});
end
obj#ss(args{:}); %# call base-class constructor
obj.c = c;
end
end
end
%# private function that extracts object properties
function props = getProps(ssObj)
props{1} = ssObj.a;
props{2} = ssObj.b;
end
Lets test those classes:
x = ss(1,2);
xx = ess(3,x)
I get:
xx =
ess handle
Properties:
c: 3
a: 1
b: 2
Methods, Events, Superclasses
Hi I am trying to implement a linked list in Matlab.
The implementation I am hoping to do is (this is the C equivalent):
class Node{
public Node* child;
}
I have looked around but don't seem to get anything quite close.
I guess that you want to implement a linked list:
classdef Node < handle
properties
Next = Node.empty(0); %Better than [] because it has same type as Node.
Data;
end
methods
function this = Node(data)
if ~exist('data','var')
data = [];
end
this.Data = data;
end
end
end
Creation :
n1 = Node('Foo'); %Create one node
n2 = Node('Bar'); %Create another one
n1.Next = n2; %Link between them
Iteration:
n = n1;
while ~isempty(n)
disp(n.Data); %Change this line as you wish
n = n.Next;
end
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.
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).