Why is SuperClass:initialize() different from SuperClass.initialize(self) in lua? - oop

When using middleclass I encountered a strange problem:
ParentClass = class('ParentClass')
function ParentClass:initialize(param)
self.param = param
end
Now this will work:
Child1 = class('Child1', ParentClass)
function Child1:initialize(param)
ParentClass.initialize(self, param)
end
But this wont:
Child2 = class('Child2', ParentClass)
function Child2:initialize(param)
ParentClass:initialize(param)
end
Creating Children like Child2 will result in a modification of param not for the single instance but for all children that inherit from ParentClass.
It took me quite a long time to identify this problem as I was sure that Object:function() is just syntactical sugar for Object.function(Object) and thus should be the same. This seems somehow not to be a problem of middleclass because a different OO library I used before showed similar problems...
What am I missing here?

function Child1:initialize(param)
ParentClass.initialize(self, param)
end
is equivalent to
function Child1:initialize(param)
ParentClass.initialize(Child1, param)
end
So self in
function ParentClass:initialize(param)
self.param = param
end
will refer to Child1
While
function Child2:initialize(param)
ParentClass:initialize(param)
end
is equivalent to
function Child2:initialize(param)
ParentClass.initialize(ParentClass, param)
end
so self in
function ParentClass:initialize(param)
self.param = param
end
will refer to ParentClass
So snippet 1 will initialize Child1 while snippet 2 will initialize the base class.

Related

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.

Calling the actual class in Matlab

Let's say I have this class:
classdef abstractGame
%UNTITLED Summary of this class goes here
% Detailed explanation goes here
properties
end
methods (Abstract, Static)
run(gambledAmount);
end
methods (Static)
function init()
gambledAmount = validNumberInput(abstractGame.getGambleString(), 1, 100, 'helpText', 'round');
end
function str = getGambleString()
str = 'How much do you want to gamble?';
end
end
end
And other classes extends from this class. I would like the child classes to redefine the getGambleString method, and for the init-method to use the one the deepest class defines (instead of abstractGame.[...] I want something like calledClass.[...]).
How should I call that?
Thanks in advance.
That is a static virtual function problem; such a construct, though, doesn't exist even in C++, then I suppose there is no chance to have it in matlab. (virtual function definition.)
Btw, in matlab, non-static methods behave as virtual (as in Java), therefore, if you accept not to use static functions, you can obtain the effect you need.
Proof (simplified code):
classdef abstractGame
function str = init(obj)
str = getGambleString(obj);
end
function str = getGambleString(obj)
str = 'How much do you want to gamble?';
end
end
end
classdef game < abstractGame
methods
function str = getGambleString(obj)
str = 'Hi!';
end
end
end
d = game;
d.init()
ans =
Hi!

Matlab equivalent to calling inside static class

Confer the following code:
classdef highLowGame
methods(Static)
function [wonAmount, noGuesses] = run(gambledAmount)
noGuesses = 'something';
wonAmount = highLowGame.getPayout(gambledAmount, noGuesses); % <---
end
function wonAmount = getPayout(gambledAmount, noGuesses)
wonAmount = 'something';
end
end
end
Is there a way to call a static method of the same class (inside a static) method without having to write the class name? Something like "self.getPayout(...)" - in case the class turns out to get to 500 lines and I want to rename it.
Not an answer to your question directly, but it's worth noting that you can also put "local functions" after the end of your classdef block in your class.m file, and these behave like private static methods, but you do not need to invoke them using the class name. I.e.
% myclass.m
classdef myclass
methods ( Static )
function x = foo()
x = iMyFoo();
end
end
end
function x = iMyFoo()
x = rand();
end
% end of myclass.m
As far as I can tell, "no" with a "but". In general, you can only specify the static method with the class name. However, you can fake your way around the restriction since MATLAB has feval:
classdef testStatic
methods (Static)
function p = getPi() %this is a static method
p = 3.14;
end
end
methods
function self = testStatic()
testStatic.getPi %these are all equivalent
feval(sprintf('%s.getPi',class(self)))
feval(sprintf('%s.getPi',mfilename('class')))
end
end
end
Here, class(self) and mfilename both evaluate to 'testStatic', so the functions above end up evaluating 'testStatic.getPi'.
Or, alteratively, you can write a non-static method, self.callStatic; then always use that. Inside that, just call testStatic.getPi. Then you'll only need to change that one line.

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.

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

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.