How to get the handle of a method in an Object (class inst) within MATLAB - oop

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

How do I pass parameter of inline new object?

I have a method that accepts a string as a parameter.
The string I need to pass is the property of an instantiated object.
I don't need the object to stick around once I get the value of that property.
I know I can do this like so:
Dim x As New myClass1
foo.thing1 = MyMethod(x.Name)
x = New MyClass2
foo.thing2 = MyMethod(x.Name)
'etc...
But I would prefer to do this inline if possible, since I have to do this several times in a row with different MyClass types.
EDIT:
Figured it out:
foo.thing = MyMethod(new MyClass().Name)
Try
foo.thing1 = MyMethod((New myClass1).Name)
foo.thing2 = MyMethod((New MyClass2).Name)
You need the braces around New myClass1, otherwise VB thinks you are trying to create an object of type myClass1.Name, which, of course, does not exist.
foo.thing = MyMethod(new MyClass().Name)

Lua & OO, how to access method from another method?

So if I have an Object and needs to call one method from another within that Object, how do I construct that call?
TestObject = {}
TestObject.__index = TestObject
function TestObject.new()
local self = setmetatable({}, TestObject)
self.value = init
-- a count [integer] of something. Not important what
self.counter = 99
return self
end
function TestObject:getCount()
return self.counter
end
function TestObject:getCountPlus(add_value)
-- HERE HOW SHOULD THIS BE FORMATED??
return self.getCount() + add_value
end
And using this Object would be something like this:
local testObject = TestObject.new()
testObject:getCountPlus(1)
which should result in 100.
The getCount() needs to know what instance it is in. When you write
function TestObject:getCount()
it is same as writing
function TestObject.getCount(self)
(note the colon changed to dot). So calling self.getCount() is like calling getCount with self=nil. Do self:getCount(), which is same as self.getCount(self). This may seem odd: why does interpreter not provide self automatically? It's just the way the language was designed: it only provides self automatically with the : notation.

Can properties of an object handle returned from a function be used without first assigning to a temporary variable?

I have a function that returns a handle to an instantiated object. Something like:
function handle = GetHandle()
handle = SomeHandleClass();
end
I would like to be able to use the return value like I would if I was writing a program in C:
foo = GetHandle().property;
However, I get an error from MATLAB when it tries to parse that:
??? Undefined variable "GetHandle" or class "GetHandle".
The only way I can get this to work without an error is to use a temporary variable as an intermediate step:
handle = GetHandle();
foo = handle.property;
Is there a simple and elegant solution to this, or is this simply impossible with MATLAB's syntax?
To define static properties, you can use the CONSTANT keyword (thanks, #Nzbuu)
Here's one example from MathWorks (with some errors fixed):
classdef NamedConst
properties (Constant)
R = pi/180;
D = 1/NamedConst.R;
AccCode = '0145968740001110202NPQ';
RN = rand(5);
end
end
Constant properties are accessed as className.propertyName, e.g. NamedConst.R. The values of the properties are set whenever the class is loaded for the first time (after the start of Matlab, or after clear classes). Thus, NamedConst.RN will remain constant throughout a session as long as you don't call clear classes.
Hmm, I don't like to disagree with Jonas and his 21.7k points, but I think you can do this using the hgsetget handle class instead of the normal handle class, and then using the get function.
function handle = GetHandle()
handle = employee();
end
classdef employee < hgsetget
properties
Name = ''
end
methods
function e = employee()
e.Name = 'Ghaul';
end
end
end
Then you can use the get function to get the property:
foo = get(GetHandle,'Name')
foo =
Ghaul
EDIT: It is not excactly like C, but pretty close.
The only way to have a static property in MATLAB is as a constant:
classdef someHandleClass < handle
properties (Constant)
myProperty = 3
end
end
then someHandleClass.myProperty will return 3.

Creating classes dynamically in matlab

Given a structure, is there a way to create a class in MATLAB? Take for instance
>> p = struct(); p.x = 0; p.y = 0;
>> p
p =
x: 0
y: 0
>> name = 'Point'
name =
Point
What I would like to do, is given a string containing the name of the class and a struct with containing the fields I would like to create a class without having to write a file explicitly writing the definition.
Right now if we use class(p) we will obtain struct. What I want to do is create an object of the type Point so that when I do class(obj) then I get Point.
Any ideas how to accomplish this besides writing a file in MATLAB with the class definition and then executing it?
Either you have specific functionality (methods) associated with the Point class as opposed to e.g. the Line class, in which case you should write out the classes by hand, anyway, or you can make a single dynamicprops class that can have dynamically created properties, and unless you really need to call a method named class, you much simplify your life by calling classname instead.
classdef myDynamicClass < dynamicprops
properties (Hidden)
myClass %# this stores the class name
end
methods
function obj = myDynamicClass(myClassName,varargin)
%# synopsis: obj = myDynamicClass(myClassName,propertyName,propertyValue,...)
%# myClassName is the name of the class that is returned by 'classname(obj)'
%# propertyName/propertyValue define the dynamic properties
obj.myClass = myClassName;
for i=1:2:length(varargin)
addprop(obj,varargin{i})
obj.(varargin{i}) = varargin{i+1};
end
end
function out = classname(obj)
out = obj.myClass;
end
end
end
I don't know of any way of creating objects dynamically, so I'd say the answer to your question is no. However, to solve your problem, I would propose something very similar to what Mikhail said:
Work with a struct with fields x, y and classname:
p.x=0;
p.y=0;
p.classname='Point';
and then write a function myclass(x) which returns x.classname. If for some reason you need to use class() you could even overload it with your own function which checks if x is one of your special structs and calls builtin('class', x) otherwise:
function out=class(varargin)
if nargin==1 && isstruct(varargin{1}) ... #check if we were given a struct
&& isfield(varargin{1}, 'classname') ... #...which contains a field classname
&& ischar(varargin{1}.classname) %# ... which is a string
out=varargin{1}.classname; %# ok, our special case :-)
else
out=builtin('class',varargin{:}); %# normal case - call builtin class()
end
One solution that I've used in the past is to write a MATLAB function that takes this information (i.e. the class name and fields) and writes an M-file containing the required classdef construct.
This works well if you're using this information to describe a prototype that you want to expand later.

Inheritance of class variables to a subclass

I'm having a huge nightmare with these subclasses and I can't figure out why this isn't working.
I have main class BODY with a subclass RECTANGLE. BODY has a function called SetWorld which does the following
function BODY:SetWorld( worldnum )
self.world = worldnum
end
Now, if I do this:
rect = RECTANGLE:new()
rect:SetWorld(1)
The value self.world is changed to 1 in the SetWorld function but if I try to use self.world in another function in BODY it always returns nil. Why is this? It works if I create a new BODY instead of a RECTANGLE, but that means I can't use my subclass.
When using a colon to call a method, the first argument is set the "self", and all other arguments are shifted. If you had supplied more code it would be easier to resolve the issue, however, I believe this may be the issue:
local x = {
new = function(o, t)
print("1st Arg", o)
print("2nd Arg", t)
end
}
x.new("Hello World")
x:new("Hello World")
Do you see how the arguments are shifted?