I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.
Related
I want to set up an object of a class, which contians all variables for a simulink model as its properties.
To later be able to use parallel simulations, I want to have a function in the methods, which takes all the properties and feeds them to a Simulink SimulationInput Object (via the 'setVariable' method),
but the setVariable-function does not fill up the variables of the object 'in' when I run it.
The code looks somewhat like this:
classdef SimSetup
properties
mdl = 'SimulinkFile'
SimulationTime = 2
Plant
in
end
methods
function this = SimSetup()
open_system(this.mdl);
this.Plant = load('PlantData.mat','xPlant');
end
function createSimIn(this)
this.in = Simulink.SimulationInput(this.mdl);
this.in = this.in.setVariable('SimulationTime', this.SimulationTime);
end
end
Thanks in advance
The mistake was the following:
I either had to use a handle class or had to return the output of the function to the object itself (in short: function this = createSimIn(this)).
In this article (https://blogs.mathworks.com/loren/2012/07/16/who-what-why-but-not-this/) near the bottom Loren says that class properties can be the same as keywords. However, how is this possible? If you write a classdef script any attempt to use a keyword (including class keywords like "events") in the properties block gets a red syntax error. Was she mistaken? I'm asking because I really want a property name to be a keyword for a particular application.
Its possible by the use of dynamic properties, for example:
classdef test < dynamicprops
methods
function obj = test()
end
end
end
var = test();
var.addprop ( 'events' );
var.events = 123;
It can make code harder to maintain and its a bit overkill if you only want to name a single property the same as a keyword, in that instance why dont you do something like capitilizing the var name, or prepending it with something - so it still reads like what you want but it doesn't cause the name clash:
classdef test
properties
Events
myIf
% etc...
end
methods
function obj = test()
end
end
end
I want to load a property on demand but i cant get it working.
I have a class with a transient property foo. So the property is not stored when the object is saved. When I use a method that is calling the property 'foo', I want that the value of foo is loaded from a separate mat file and stored into the object as long as it is in workspace.
I tried something with get and set methods but cant get it working. Is this possible? Or do I always add a line of code that is loading the property? The following code does not do what I want but it gives an indication what i tried.
In addition, the code below keeps loading the foo.mat file when the property is used. I want to load foo.mat only one time and store it as a property and retrieve the data from there instead of loading. The reason for my question is that the foo property is rather large i.e. a class with many properties in itself. I only want to load it when it is needed and dont want to store it in foobar class itself.
classdef foobar
properties(Transient = true)
foo
end
methods
function value = get.foo(obj)
if isempty(obj.foo)
value = load('foo.mat');
disp('load foo.mat');
end
end
function obj = set.foo(obj,value)
obj.foo = value;
end
end
end
You have two major problems here:
In your get.foo method, once you load the value, you never update the value of foo in the object, so it remains empty.
Even if you tried to update foo in your get.foo method, it would still be empty in the original object because your foobar class is a value class. Methods that modify a value class object have to return the modified object as an output, because they are essentially modifying a copy of the object. A set method of a value class returns a modified object that is used to overwrite the original object, but get methods don't return modified objects (since they aren't generally expected to modify them). To get around that limitation, you'll need the reference-like behavior of a handle class (here's a related question you may want to take a look at for more background).
So, in order to get the behavior you want you'd have to implement foobar as a subclass of the handle class and update the foo field when you first load it:
classdef foobar < handle % Inherit from handle class
properties(Transient = true)
foo
end
methods
function value = get.foo(obj)
if isempty(obj.foo)
value = load('foo.mat');
disp('load foo.mat');
obj.foo = value; % Update foo
end
value = obj.foo; % Return current foo value
end
function set.foo(obj, value) % Return value is unnecessary for handle class
obj.foo = value;
end
end
end
This should now give you the behavior you want (i.e. foo is only loaded when it is first accessed).
Note: Any method that invokes get.foo will initialize foo. One method you may overlook, because it's created by default for a class, is the disp method. The default display for a class object will show the class name followed by a list of non-hidden public properties and their values. Note what happens when I create an object of class foobar from above with and without a semicolon:
>> f = foobar; % Display is suppressed
>> f = foobar
f =
load foo.mat % foo gets initialized...
foobar with properties:
foo: [1×1 struct] % ...because its value is displayed here
If you want to avoid this, you can overload the disp function for your foobar object so that displaying the object doesn't access (and thus initialize) foo. For example, you can add this method to the above foobar class:
function disp(obj)
disp(' foobar object');
end
Now you won't initialize foo when displaying the object:
>> f = foobar
f =
foobar object % foo not yet initialized
>> a = f.foo;
load foo.mat % foo initialized because we accessed it
I would like to access the class name of the concrete class that's invoking a static method implemented in an abstract superclass.
This is the code (part of) of the abstract superclasss:
classdef (Abstract) AbstractJobProcessor < handle
properties (Abstract, Constant)
VERSION_MAJOR;
VERSION_MINOR;
LAST_MODIFIED;
end
...
methods (Static)
function res = getVersionMajor;
res = AbstractJobProcessor.VERSION_MAJOR;
end
function res = getVersionMinor
res = AbstractJobProcessor.VERSION_MINOR;
end
function res = getVersionInfo
res = sprintf('**CLASSNAME**: v%d.%02d (last modified: %s)',...
AbstractJobProcessor.VERSION_MAJOR,...
AbstractJobProcessor.VERSION_MINOR,...
AbstractJobProcessor.LAST_MODIFIED);
end
end
...
Basically, I would like to access the classname of the concrete subclass and use it in the method getVersionInfo in place of the string **CLASSNAME**.
All the methods returning meta information about a class (that I have found in the documentation) require a reference to an instance of the class (like, for example, mc = metaclass(object)).
The below function will give you what you want - subclass name, that was used when invoking an (inherited) static superclass method. Just call it inside your superclass method like you would any normal function:
className = getStaticCallingClassName();
What it does handle:
Both the case when method was invoked programmatically (i.e. by a running script / function), as well as when it was invoked from the command window.
Arbitrarily nested package names (i.e. classes located inside directories prefixed with +).
What it does not handle:
Does not work if the static method is called in a non-static context, i.e. on an object instance. But you should not be using such syntax anyway. This would've been possible if we were able to use evalin with 'caller' workspace recursively, but it does not work this way.
A brief explanation behind the idea: second entry in the stack trace, produced by dbstack, would correspond to the superclass, which we can use to extract the static method name. The next steps depend on:
If the method is invoked programmatically, third stack entry would point us to a line in the the parent script/function which we need to read, e.g. using dbtype. All that's left to do is extract the subclass name using regexp based on the method name.
If the method is invoked from command window, we query the last command and use that as the input for our regular expression.
Note that even if stack has 3 entries or more, it doesn't mean that the method was invoked programmatically. For example, if we've stopped on a breakpoint somewhere and invoke the method from command window, stack trace would be long, but regexp based on the line from the third stack trace entry will not give us the answer. In this case we fall back to the command window approach.
Warning: it heavily relies on undocumented features and may break in any feature release. Tested on Matlab 2015b, but should work on most previous releases as well. Some may say it is quite dirty, but it works very well, and it's the only method that I'm aware of to achieve such a behavior.
function [className, fullPath] = getStaticCallingClassName()
ST = dbstack('-completenames');
% First one is getStaticCallingClassName, second one is the superclass
methodName = char(regexp(ST(2).name, '[^\.]([^.]*)$', 'match'));
% matches string (combination of alphanumeric/underscore/dot characters) preceeding the given method call.
pattern = sprintf('[\\w.-]*(?=.%s)', methodName);
% If the parent called static method programmatically, we should be able to find it via the next (third) stack trace
if length(ST) > 2
command = evalc('dbtype(ST(3).file, num2str(ST(3).line))');
className = char(regexp(command, pattern, 'match'));
else % was likely called from command window. Long stack trace means that we're simply waiting in a breakpoint somewhere
className = []; % go straight to command window approach
end
if isempty(className) % means that static method was called directly from command window
javaHistory = com.mathworks.mlservices.MLCommandHistoryServices.getSessionHistory();
command = char(javaHistory(end));
className = char(regexp(command, pattern, 'match'));
end
fullPath = which(className);
end
Here's a workaround. According to the MATLAB documentation:
'Ordinary methods define functions that operate on objects of the class',
'Static methods are (1) associated with a class, but (2) not with specific instances of that class'.
You can have both aspects of static methods if you call an ordinary method with an empty object array.
For example, suppose we have a base class:
classdef base
methods
function obj = base()
disp('constructor called')
end
function dispClassName(obj)
disp(['class name = ', class(obj)]);
end
end
end
and a subclass
classdef sub < base
end
Now call the methods as follows (this will not invoke any constructor):
>> base.empty.dispClassName
class name = base
>> sub.empty.dispClassName
class name = sub
A real solution (for which I did an enhancement request 03315500 to MathWorks) would be to extend the MATLAB language with a method attribute 'Class' to define methods that are associated with the invoking class (similar to the Python #classmethod decorator). Methods of this class would automatically receive the metaclass of the invoking function as a first argument. With such an extension we could define a base class:
% Future MATLAB syntax extension
classdef base
methods(Class) % New method attribute ‘Class’
function dispClassName(cls) % implicit argument (meta.class)
disp(['class name = ' cls.Name ]);
end
end
end
and a subclass
classdef sub < base
end
and call
>> base.dispClassName
class name = base
>> sub.dispClassName
class name = sub
Given an object with custom get-methods for some properties, does Matlab execute some of the code (the getter) before the class constructor is executed?
Even if i set the default of a property to empty, and have a getter (!) open an io connection to a file, when I step through the debugger, even on the first line the object is already defined as file.io (with a filepath that corresponds the information available to the object before the constructor ran). How can this be, and whats the reasoning behind this implementation?
Edit: A breakpoint in the get method does not halt the debugger, so I'm not sure wether it is actually executed or not.
Edit 2: It seems like the getter is executed after the constructor is entered, after the debugger halts in the first line, before the first line is executed. No halt at breakpoint within get method though...
As per request, some code:
classdef Cat < handle
properties
filename
poop = []; % my data matrix the cat is there to produce/manage
end
methods
function obj = Cat(config)
obj.filename = config.FILENAME; % Halt debugger in this line
end
function value = get.poop(obj)
obj.poop = matfile(obj.filename)
value = obj.poop.ingredients; % 'ingeredients' being the name of the variable in poopfile.mat
end
end
end
To debug, I call
myCat = Cat(config)
from a different script. Workspace is cleared and path is rehashed.
When the debugger halts, obj.poop is not [], but is already a reference to some undefined file, and the reference to the linked file obj.poop.Source is empty, which is obvious, as obj.filename has not been set yet.
Test setup:
With a slightly modified class Cat.m:
classdef Cat < handle
properties
filename
poop = [];
end
methods
function obj = Cat(config)
display('In constructor.');
obj.filename = config.FILENAME;
end
function value = get.poop(obj)
display('In poop getter.');
obj.poop = matfile(obj.filename);
value = obj.poop.ingredients;
end
end
end
to display the execution order of the class methods, and the test.m script:
ingredients = 1:100;
save('a', 'ingredients');
config.FILENAME = 'a.mat';
myCat = Cat(config)
I got the following result:
>>test
In constructor.
myCat =
In poop getter.
Cat handle
Properties:
filename: 'a.mat'
poop: [1x100 double]
Methods, Events, Superclasses
Please note that the first assignment in the getter method was ended with semicolon (while in the original code was not).
In conclusion:
The get.poop() method is called after the constructor, as expected. This was tested on MATLAB R2012a, but I strongly believe that this is not a matter of version.
The reason for which get.poop() method is called is because the assignment myCat = Cat(config) is not ended with a semicolon ;.
Rationale:
The default behavior for assignments not ended with semicolon is to display the result of assignment. Displaying an object means, among other things, displaying the values of public properties. To get the value of the public property poop, get.poop() is called; that explains the getter call. Once the statement is changed to myCat = Cat(config);, the getter is not called anymore, because the result of assignment is not displayed anymore.
Later note:
Please note also that every request for display of the object will call the getter. So, yes, the getter might be called while the constructor is still halted by the debugger, because you inspect the poop member.