I'm trying to access a class property from within a method function. When I modify the property from the constructor, the setter is called and the property is changed. But when I modify the property from another method, the property reverts to the previous value, when the function is terminated, even though the setter is called again.
What is wrong with my code, please help me!
Thanks
The code is below:
classdef random
properties
x
end
methods
function obj=random(obj)
obj.x = 2
obj.foo(1)
obj %output x:2, but it should be 1!
end
function foo(obj,A)
obj.x = A;
obj %output x:1
end
function obj = set.x(obj,newVal)
obj.x = newVal;
end
end
end
Somebody correct me if I am wrong, but I assume the obj in foo is passed by value. So it does get updated within that function space but not returned. So what works is to have it return the object and catch that in the constructor. Try:
classdef random
properties
x
end
methods
function obj=random(obj)
obj.x = 2;
obj = obj.func1(4);
disp(obj.x);
end
function [obj] = func1(obj,A)
obj.x = A;
disp(obj.x);
end
function obj = set.x(obj,newVal)
obj.x = newVal;
end
end
end
Related
As the title says I am setting a property with the constructor and would like to access the property later as a get function that is static. How would I do this in MATLAB?
classdef Wrapper
properties(Access=public)
dataStruct
end
methods
function data = Wrapper(filePath)
if nargin == 1
data.dataStruct=load(filePath)
end
end
end
methods(Static)
function platPosition = getPlatPosition()
platPosition = dataStruct.someField
end
end
end
--------------------------
import pkg.Wrapper.*
test = Wrapper('sim.mat')
pos = test.getPlatPosition
As far as I know MATLAB doesn't have static properties like other OOP languages [ref]. Only static properties can be used inside the static methods. The closest you can get in MATLAB classes to static property is Constant property. The downside is the constant property has to be initialized and is read-only. Inside the static method, You can access read-only/constant property with class name.
classdef Wrapper
properties(Constant=true)
dataStruct=load('\path\to\sim.mat');
end
methods
function data = Wrapper()
%do something with object
end
end
methods(Static=true)
function platPosition = getPlatPosition()
platPosition = Wrapper.dataStruct.Fieldname;
end
end
end
In your case, you could accept object as an input argument of your static method.
classdef Wrapper
properties(Access=public)
dataStruct
end
methods
function data = Wrapper(filePath)
if nargin == 1
data.dataStruct=load(filePath)
end
end
end
methods(Static)
function platPosition = getPlatPosition(obj)
platPosition = obj.dataStruct.someField
end
end
end
--------------------------
import pkg.Wrapper.*
test = Wrapper('sim.mat')
pos = test.getPlatPosition(test);
I work within a project which has several classes which define properties that use essentially the same set method. To make the code more readable, I want to implement a commonSetter method. The overall goal is to include this commonSetter method in the superclass, so that all the classes could use it.
The question was already posted here, but unfortunately, the answer is not working. I changed the code to the following, but get the error: Maximum recursion limit of 500 reached.
classdef MyClass
properties
A
B
end
methods
function mc = MyClass(a,b) % Constructor
mc.A = a;
mc.B = b;
end
function mc = set.A(mc, value) % setter for A
mc = mc.commonSetter(value, 'A');
end
function mc = set.B(mc, value) % setter for B
mc = mc.commonSetter(value, 'B');
end
end
methods(Access = protected)
function mc = commonSetter(mc, value, property)
% do some stuff
disp('Made it into the commonSetter!')
mc.(property) = value;
end
end
end
So far I know that there is an infinite loop where mc.(property) = value; calls set.A (or set.B), which in turn calls commonSetter.
In my post # MathWorks the following was suggested:
To break that loop I guess you should look at builtin() and subsasgn(). Maybe Overriding subsref and subsasgn - effect on private properties can be of some help.
Currently, I have troubles realizing the suggestions and additionally not very comfortable to overwrite subsasgn() as I'm not sure how it will affect the overall project. I would like to know, if someone has other ideas or knows how to overwrite subsasgn() safely.
To solve the recursion error, you could just let the commonSetter method output the new value instead of the object.
classdef MyClass
properties
A
B
end
methods
function mc = MyClass(a, b)% Constructor
mc.A = a;
mc.B = b;
end
function mc = set.A(mc, value)% setter for A
mc.A = mc.commonSetter(value, 'A'); % update mc.A
end
function mc = set.B(mc, value)% setter for B
mc.B = mc.commonSetter(value, 'B');
end
end
methods (Access = protected)
function new_value = commonSetter(mc, value, property) % only return the new value
% do some stuff
disp('Made it into the commonSetter!')
if value > 5
new_value = -10;
else
new_value = value;
end
end
end
end
I would like to create a class that (for simplicity) adds two numbers as soon as I change an input parameter in an instance of the class. For simplicity I have created this class:
classdef test < handle
properties (Constant)
privatNummer = 10;
end
properties
brugerNummer;
sum;
end
methods
function obj = test()
obj.sum = method1(obj);
end
function obj = method1(obj)
obj.sum = obj.brugerNummer + obj.privatNummer;
end
end
end
How do I get it to automatically update obj.sum when I give it a new value? Currently I have to run obj.method1 every time I want to update obj.sum.
I have tried something like this (but I just can't get it working):
classdef test < handle
properties (Constant)
privatNummer = 10;
end
properties
brugerNummer;
sum;
end
methods
function obj = test()
notify(obj,'StateChange')
obj.sum = method1(obj);
addlistener(obj.brugerNummer,'Ændret nummer',#RespondToToggle.method1);
end
function src = method1(src)
src.sum = src.brugerNummer + src.privatNummer;
end
end
events
StateChange
end
end
I developed two solutions for the problems. The first relying on Dependent properties, setters and getters; the second relying on listeners and callback-functions.
First Solution:
classdef test
properties (Constant)
privatNummer = 10;
end
properties
brugerNummer;
end
properties (Dependent)
sum;
end
methods
function obj = test()
% Constructor
end
function value = get.sum(obj)
value = obj.brugerNummer + obj.privatNummer;
end
end
end
Second Solution (this was a real hassle):
classdef test < handle
properties (Constant)
privatNummer = 10;
end
properties (SetObservable)
brugerNumber;
end
properties
sum;
end
methods
function obj = test()
% constructor
addlistener(obj, 'brugerNumber', 'PostSet',#test.callbackFun);
end
end
methods (Static)
function callbackFun(~,evnt)
obj = evnt.AffectedObject;
obj.sum = obj.brugerNumber + obj.privatNummer;
end
end
end
I am starting with oop in Matlab and seem to miss something.
classdef car < handle
properties (Access = public)
a
b
end
methods
function obj = update(obj)
obj.b = updateB(obj.a, obj.b);
end
function B = updateB(a, b)
B = a + b;
end
end
end
I get the famous Undefined function 'updateB' for input arguments of type 'double'. error every time, I try to call the function update. Oddly, it works if I change updateB to:
function B = updateB(obj)
B = obj.a + obj.b;
end
What am I missing? I do not always want to call updateB with obj, because I want to use the function without using the actual object's properties.
When, if you don't want the method to rely on a specific instance, use this approach:
methods
function obj = update(obj)
obj.b = car.updateB(obj.a, obj.b);
end
end
methods (Static)
function B = updateB(a, b)
B = a + b;
end
end
I have a class that encapsulates access to an array in a wierd way;
The class constructor takes a function handle which is some kind of transformation of indexes before passing them to the array
classdef MyClass
properties
arr
accessHandle
end
methods
function obj = MyClass(array, trans)
obj.arr = array;
obj.accessHandle = #(i) obj.arr(trans(i))
end
end
The problem is the anonymous function copies the array into it's own workspace and if we change the array, it doesn't change in the function.
Essentially what is needed is to pass to the anonymous function the 'this' pointer/reference like in Java/C++/etc
The simple solution is to create a handle to the array and pass it along to the function:
classdef MyClass
properties
arr
accessHandle
end
methods
function obj = MyClass(array, trans)
obj.arr = array;
tmp = PropertyReference(obj, 'arr'); %See http://stackoverflow.com/questions/7085588/matlab-create-reference-handle-to-variable
%for the definition
obj.accessHandle = #(i) tmp(trans(i));
end
end
end
The problem now is when I pass an instance of the class to a function, the reference passed still refers to the object outside the function:
function foo(ins)
ins.arr = [1 2];
disp(ins.accessHandle(1));
end
cl = MyClass([0 3], #(x) x);
foo(cl) //output 0 instead of 1
disp(ins.accessHandle(1)) //output 0
EDIT: The class should be a value class, the semantics are that when a copy of the class is made, the accessHandle field changes the array handle it uses.
How can I achieve the right semantics ?
Currently, your class is a value class (MATLAB's default). If you want to be able to pass objects around by reference (changes will be reflected in the original object), you'll to make it a handle class by subclassing handle
classdef MyClass < handle
properties
arr
accessHandle
end
methods
function obj = MyClass(array, trans)
obj.arr = array;
obj.accessHandle = #(i) obj.arr(trans(i))
end
end
end
And then you can use it the way you expect
m = MyClass([1 2 3], #(x)x);
m.accessHandle(2)
% 2
m.arr(2) = 5;
m.accessHandle(2)
% 5
More information about the difference between the two can be found here.
Edit
If you need MyClass to be a value class, then you could store the trans value as a property and then have a normal method to access the value
classdef MyClass
properties
arr
trans
end
methods
function obj = MyClass(array, trans)
obj.arr = array;
obj.trans = trans;
end
function res = access(obj, k)
res = obj.arr(obj.trans(k));
end
end
end
Or if you want, you could make accessHandle a dependent property that returns a function handle.
classdef MyClass
properties
arr
trans
end
properties (Dependent)
accessHandle
end
methods
function obj = MyClass(array, trans)
obj.arr = array;
obj.trans = trans;
end
function res = get.accessHandle(obj)
res = #(i)obj.arr(obj.trans(i));
end
end
end