What does dot notation for classes, properties and methods mean? - matlab

I'm a relative newbie to programming, except having used basic capabilities of Matlab for several years (manipulating arrays, linear algebra, functions, scripts, etc.) and am very recently starting to explore the object oriented side of the program (which is also my first foray into any object oriented programming!).
My biggest sticking point right now is understanding what the heck this dot notation means. For example, say I write the simple class
classdef alchemy
properties
element
end
methods
% CONSTRUCTOR
function e = alchemy
e.element = ' ';
end
end
end
What does the e.element actually mean? Then typing into the command line
e.element = 'LEAD'
assigns the string 'LEAD' to one instance of the property element of the class alchemy.... Why does it do this?
Now say I add the method
function e = transmute(e)
oldElem = e.element;
if oldElem == 'LEAD'
e = 'GOLD';
elseif oldElem == 'GOLD'
e = 'LEAD';
else
disp('Oh no! This is a non-transmutable element.');
end
end
I can now put in the command line e = e.transmute and it will return
e =
GOLD
What is going on in this situation with the dot notation? Why does e.transumte apply the function transmute to e? I'm really confused by this whole notation, and none of Matlab's help-pages give me any deeper inkling. Any help would be appreciated!

The dot notation is used for a property/attribute of the object or for invoking a method.
It has both meanings.
name_object.abc
will give you the value of abc if abc is a property of name_object, or will invoke abc on name_object if abc it's a method.

The class (or object) in Matlab is a collection of properties and methods.
Maybe what is confusing is that your method transmute accepts the object (it should) but returns a string with the same variable name as the original object. It is more or less a "get value of" method. Not a transmute object.
In this way it returns the transmuted object.
function e = transmute(e)
switch e.element
case 'LEAD'
e.element = 'GOLD';
case 'GOLD'
e.element = 'LEAD';
otherwise
disp('Oh no! This is a non-transmutable element.');
end
end
You can also call the method like this:
e = transmute(e)
It is equal to
e = e.transmute

Related

Why are the values passed to a method saved as an object?

I have a class with a scheduler function that is supposed to insert characters into a cell array:
classdef timeline < handle
properties
schedule
i
%other properties
end
methods
%other functions
function t = timeline()
%other initializations
t.schedule = cell(1,738);
t.i = 1;
end
function scheduler(t, g, fT)
if nargin == 2
fT = t.i;
end
if strcmp(g,'science')
'science' % eclipse occurs after
for j = (fT+t.sTime+1) : (fT+t.sTime+1+t.eTime)
t.schedule{j} = 'e';
end
elseif strcmp(g,'pass')
'pass' % science occurs 2 hrs after end
for j = (fT) : (fT+t.pTime)
t.schedule{j} = 'p'
end
for j = (fT+t.pTime+121) : (fT+t.pTime+120+t.sTime)
t.schedule{j} = 's';
end
scheduler(t, 'science', fT+t.pTime+120);
end
end
end
end
In the command window, I define my object t = timeline() and a mode g = 'pass' and then call the scheduler, t.scheduler(t,g).
It doesn't change the schedule property. What's going on inside the if statements to write the schedule isn't the problem I am concerned with. I put outputs in each part of the if statement, and found that strcmp is returning false and skipping over the whole block. So, I added a break point in the scheduler function, and found that for some reason g is passed to the function as another timeline object instead of the string 'pass'. Why is this?
When you call a method for an object you can use dot notation or function notation. Dot notation means you call the method using the dot operator on the object instance. For example,
obj.methodName(args);
In function notation you pass the object instance variable as the first argument to the method. For example,
methodName(obj, args);
Both the above calls are equivalent and call the same method in the object. In both the calls MATLAB passes obj as input to the method. Note the absence of obj as an argument in the dot notation. In dot notation obj, is added as an input argument before your args. In your code you are mixing both of these options. So you got two obj arguments for your method.
Relevant documentation is at http://www.mathworks.com/help/matlab/matlab_oop/method-invocation.html

MATLAB CLASSES getter and setters

I come from a Java background. I am having issues with classes in Matlab particularly getters and setters. getting a message saying conflict between handle and value class I'm a little lost with what to do so any help for lack of a better word will be helpful.
classdef Person
properties(Access = private)
name;
age;
end
methods
% class constructor
function obj = Person(age,name)
obj.age = age;
obj.name = name;
end
%getters
function name = get.name(obj)
end
function age = get.age(obj)
end
%setters
function value = set.name(obj,name)
end
function value = set.age(obj,age)
end
end
end
Implementation
Since your class is currently a subclass of the default Value class, your setters need to return the modified object:
function obj = set.name(obj,name)
end
function obj = set.age(obj,age)
end
From the documention: "If you pass [a value class] to a function, the function must return the modified object." And in particular: "In value classes, methods ... that modify the object must return a modified object to copy over the existing object variable".
Handle classes (classdef Person < handle) do not need to return the modified object (like returning void):
function [] = set.name(obj,name)
end
function [] = set.age(obj,age)
end
Value vs. Handle
Going a bit deeper, the difference between a Value class and a Handle class lies mostly in assignment:
Assigning a Value class instance to a variable creates a copy of that class.
Assigning a Handle class instance to a variable create a reference (alias) to that instance.
The Mathworks has a good rundown on this topic.
To paraphrase their illustration, the behavior of a Value class is
% p is an instance of Polynomial
p = Polynomial();
% p2 is also an instance of Polynomial with p's state at assignment
p2 = p;
and of a Handle class is
% db is an instance of Database
db = Database();
% db2 is a reference to the db instance
db2 = db;
Quick'n Dirty from the Java perspective:
- "handle" classes are what your mind is set to. proper object instances with pointers to them. use them.
- "value" classes are always returning a full clone of whatever object (which has been modified by what you just did, e.g. setting a name).
the reason they have both in Matlab is that in Matlab you would expect the "value" behaviour natively. Imagine you have a matrix A = [1 2; 3 4], then assign that via B = A. if you now set B(1) = -1 you'd hope that A(1) is still 1, right? this is because matlab keeps track of "copies" and truly creates them as you modify different variables initially set to the same matrix. in OOP you'd have A(1)=-1 now as everythings an object reference.
furthermore, "native" matlab routines dont have a "this/self/me" variable that contains the instance reference to access from within functions. instead, the convention is that the class instance will be prepended to the function's argument list.
so for a function call myclass.mymethod(arg1,arg1), the declaration must be
function mymethod(this, arg1, arg2)
% Note that the name you choose for "this" is arbitrary!
end
mind you, this is the java-perspective (and also my favourite one), the above function call is equivalent to mymethod(myclass,arg1,arg1). this is more native to matlab-style, but somehow makes it harder to see you're calling an objects method.
now, regarding setters/getters: for handle classes, everything feels java-ish now:
classdef MyClass < handle
properties
MyProp;
end
methods
function set.MyProp(this, value) %Note: setMyProp is also valid!
... % do checks etc, trigger calls,
this.MyProp = value;
end
function value = get.MyProp(this)
... % notify, update, triggers etc
value = this.MyProp;
end
end
Of course it goes without saying that you dont need to define a getter if you just want to return the value, i.e. myclassinstance.MyProp will work without any just as well.
Finally, getters/setters for value classes are something that [never encountered me/i never needed] in my 7 years of matlab oop, so my advise would be to go with handle classes and enjoy happy matlab coding :-)
otherwise, the above explanation & official matlab docs is doing the job for value class getter/setters.

overloading the "dot" operator in MATLAB

I have written a simple class in MATLAB to manage a set of key-value pairs. I would like to be able to access the keys using a dot after the object name like:
params.maxIterations
instead of:
params.get('maxIterations')
Is it possible to override the dot operator so that it calls my get() method?
I have tried to override the subsasgn() method as suggested here but I couldn't figure out how I should write it.
You could use dynamic properties. Then instead of adding a list of strings, you add a new property for each 'key'. Get all keys with properties(MyClass) (of just fieldnames(MyClass)
However, I think it's indeed best to overload subsref, but note that doing that properly can eat away the majority of a work week if you do it for the first time...It's not that it's really difficult, it's just that the () operator does so much :)
Luckily, you don't have to. Here's how:
classdef MyClass < handle
methods
function result = subsref(obj, S)
%// Properly overloading the () operator is *DIFFICULT*!!
%// Therefore, delegate everything to the built-in function,
%// except for 1 isolated case:
try
if ~strcmp(S.type, '()') || ...
~all(cellfun('isclass', S.subs, 'char'))
result = builtin('subsref', obj, S);
else
keys = S.subs %// Note: cellstring;
%// could contain multiple keys
%// ...and do whatever you want with it
end
catch ME
%// (this construction makes it less apparent that the
%// operator was overloaded)
throwAsCaller(ME);
end
end % subsref method
end % methods
end % class

Lua - How to pass object's function as parameter to another function

local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(v1, v2)
v2(100);
end
b:test2(_, a.test1)
Doesn't work. Value is nil. I could find a solution doing an encapsulation in an anonymous function
b:test2(variable, function(value) a:test1(value) end)
But I find it pretty bad mkay
What is the correct syntax ?
anotherObject:aFunction(variable, object.doStuff) is the correct syntax.
Using a colon : with a function is just syntactic sugar for a call or declaration with an implicit self parameter as the first argument. If you would like to follow the pattern you've shown in your example in a cleaner way, you could use a helper function.
local function bind(t, k)
return function(...) return t[k](t, ...) end
end
You then apply it like so.
anotherObject:aFunction(variable, bind(object, 'doStuff'))
Edit: I believe the solution to your problem will require binding at some level, without resorting to modifying the Lua interpreter or using a code translation step.
This is fundamentally because functions in Lua do not carry any information about their origin. I.e., tables do not inherently own the functions that they store.
For example, the following is perfectly legitimate Lua code.
function Circle:area() -- function Circle.area(self)
-- ...
end
-- Evaluate the function in the "area" slot with Square as the self parameter.
Circle.area(Square)
Of course, you could try a paradigm shift, but it may be too late for that if you're building an entire application based on the idea of functions being tied to the table that they have been indexed from, as you said.
Therefore, I propose the following crazy solution.
local mt = {}
function mt:__index(k)
local v = self._slots[k]
if v == nil then
-- Ascend the inheritance tree.
-- This has to be done with rawget all the way up,
-- otherwise inherited functions would be repeatedly bound.
local p = self
repeat
p = rawget(p, '_parent')
if not p then break end
v = p._slots[k]
until v
end
if type(v) == 'function' then
-- Return a self-bound version of the function.
return function(...) return v(self, ...) end
end
return v
end
function mt:__newindex(k, v)
self._slots[k] = v
end
--- Demo & Tests ---
local function Object(parent)
local o = setmetatable({_slots = {}}, mt)
if parent then rawset(o, '_parent', parent) end
return o
end
local o1 = Object()
local o2 = Object(o1)
assert(o1.abc == nil, 'o1.abc should be nil')
o1.abc = 3
assert(o1.abc == 3, 'o1.abc should be 3')
assert(o2.abc == 3, 'o2.abc should be 3, inherited from o1')
o2.abc = 7
assert(o2.abc == 7, 'o2.abc should be 7, overriding o1')
assert(o1.abc == 3, 'o1.abc should be 3, unaffected by o2 setter')
function o1:test(bar)
return self.abc + bar
end
assert(type(o1.test) == 'function', 'o1.test should be a function')
assert(type(o2.test) == 'function', 'o2.test should be a function, inherited from o1')
assert(o1.test(5) == 8, 'o1.test(5) should return 3 + 5 = 8')
assert(o2.test(11) == 18, 'o2.test(11) should return 7 + 11 = 18')
function o2:test2(fn)
return self.abc + fn(7)
end
assert(o2.test2(o1.test) == 17, 'o2.test2(o1.test) should return 7 + (3 + 7) = 17')
o2.test3 = o1._slots.test -- proper function copying
assert(o2.test3(11) == 18, 'o2.test3(5) should return 7 + 11 = 18')
o2.abc = nil
assert(o2.abc == 3, 'o2.abc should be 3 again, inherited from o1 after clearing')
o2.abc = false
assert(o2.abc == false, 'o2.abc should be false, __index needs to differentiate between nil and false')
This metatable will provide you with what you want, with inherited and bound functions to boot. You will just need to make sure that all of the tables that you want to follow this pattern also follow the method of object creation shown in the example code.
To explain, each table made in this way has any new assignment redirected into the _slots sub-table and any new retrieval checked up the _parent inheritance tree. If the type of the value is a function, then it returns a new closure with the original self that started the check bound to the function found.
Obviously, calling a function from one of these objects with the : colon syntax is going to be a silly idea, since it would evaluate to o.fn(o, o), and that is probably not what you want. Another caveat is that copying functions onto these objects, from these objects, will not work as expected. o1.newfn = o2.fn will put an o2 bound function into o1, which in turn will be re-bound to o1. The end result would be something like o2.fn(o2, o1). You will have to copy functions from the _slots table.
In conclusion: Even though this works, I would not personally recommend it in the long run, since it may be confusing to anyone used to how Lua works with tables, indexing, and functions, and there will be overhead. You might be able to do away with some it via memoizing the closures, but I'll leave that decision up to you. Good luck!
Object method declared with : needs object instance as the first parameter. It gets added automatically if you call it with :, but as you passed just a function pointer, you need to pass this as well. This means whenever you pass a function in some object somewhere, you also have to pass object instance. This works:
local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(obj, v2)
v2(obj, 100); -- object instance is always the first param of a ":"-style func
end
b:test2(a, a.test1) -- passing object instance and a function
Building on #ryan-stein's neat bind() solution, in a module I've found this to be slightly more concise:
local m = {}
m.__index = m
m.word = 'bar'
function m:bind(fn)
return function(...) return self[fn](self, ...) end
end
function m:foo(fn)
print("Foo " .. self.word)
end
function m:start()
hs.timer.new(42, self:bind('foo'))
end
your code will be work. the reason Ryan has said.
I doubt that in the function anotherObject:aFunction(), you were using a wrong way to call the object.stuff.The correct way as this:
local a = {}
function a:test1()
print(1)
end
local b = {}
function b:test2(v1, v2)
v2();
end
b:test2(_, a.test1)

passing a colon as argument of a function in matlab

I would like to know if it's possible to use a colon ":" as argument of a function.
Something like that:
function y=func(x)
if x is a colon
do this
else
do that
end
Also is it possible to pass the key work end as argument of a function, and also 1:end, 3:end-5, etc...
I doubt it's possible, but I would like to be sure.
Also, I get a weird error when I pass "1:end" as argument of a function, it produces no error, but inside the function, no argument is assigned (not even the other arguments). Do someone know what happens?
You can override both for your own classes:
classdef MyClass
properties(Access=public)
data
end
methods
function out = end(A,k,n)
disp(A);
disp(k);
disp(n);
out = [];
end
function B = subsref(A,S)
disp(S);
B = [];
end
end
end
As for functions, I never heard of such a functionality.
No, it's not possible to pass a colon as an argument (it doesn't make any sense).