I'm new to MATLAB, and I want to write a method of a class that change the property of this object:
classdef Foo
properties
a = 6;
end
methods
function obj = Foo()
end
function change(obj,bar)
obj.a = bar
end
end
end
foo = Foo()
foo.change(7) //here I am trying to change the property to 7
It turns out the property is still 6.
MATLAB makes a difference between value classes and handle classes. Instances of value classes are implicitely copied on assignments (and hence behave like ordinary MATLAB matrices), instances of handle classes are not (and hence behave like instances in other OOP languages).
Therefore, you have to return the modified object for value classes:
classdef ValueClass
properties
a = 6;
end
methods
function this = change(this, v)
this.a = v;
end
end
end
Call it like this:
value = ValueClass();
value = value.change(23);
value.a
Alternatively, you can derive your class from the handle class:
classdef HandleClass < handle
properties
a = 6;
end
methods
function change(this, v)
this.a = v;
end
end
end
And call it like this:
h = HandleClass();
h.change(23);
h.a
There's more information in the MATLAB documentation.
Related
Take a look at the following minimal working example,
ClassA.m
classdef ClassA < handle
properties
h1 = 0;
h2 = 0;
end
methods
function obj = ClassA(n1,n2)
if nargin == 2
obj.h1 = n1;
obj.h2 = n2;
end
end
end
end
ClassB.m
classdef ClassB < handle
properties
a = ClassA;
a0 = ClassA;
end
methods
function obj = ClassB(n1,n2)
if nargin == 2
obj.a.h1 = n1.h1;
obj.a.h2 = n1.h2;
obj.a0.h1 = n2.h1;
obj.a0.h2 = n2.h2;
end
end
end
end
main.m
h1 = ClassA(1,1);
h2 = ClassA(2,2);
h3 = ClassA(3,3);
h4 = ClassA(4,4);
x01 = ClassB(h1,h2);
x01.a.h1
x01.a.h2
x12 = ClassB(h3,h4);
x01.a.h1 % should keep its value as 1
x01.a.h2 % should keep its value as 2
The problem occurs when I instantiate a second object of class B which causing x01 to be overwritten. I think this has to do with handle class. Is there any clever way to avoid this problem? Notice ClassA must be handle since I need to modify its properties.
Note what is described in the documentation (emphasis mine):
There are two basic approaches to initializing property values:
In the property definition — MATLAB evaluates the expression only once and assigns the same value to the property of every instance.
In a class constructor — MATLAB evaluates the assignment expression for each instance, which ensures that each instance has a unique value.
This means that, for class B, a = ClassA is evaluated only once, and then every object of that class created gets a copy of a. But because ClassA is a handle object, all objects end up pointing to the same object (it is the handle that is copied, not the object).
So, the solution is follow the 2nd method to initialize property values: in the class constructor:
classdef ClassB < handle
properties
a;
a0;
end
methods
function obj = ClassB(n1,n2)
obj.a = ClassA;
obj.a0 = ClassA;
if nargin == 2
obj.a.h1 = n1.h1;
obj.a.h2 = n1.h2;
obj.a0.h1 = n2.h1;
obj.a0.h2 = n2.h2;
end
end
end
end
I want to have a simple static member in a class with simple access i.e I like to have a class_name.static_data instead of class_name.shared_obj.static_data.
I've searched and find the standard method of defining static members in Matlab classes, on mathwork.com as you can see below.
classdef SharedData < handle % an auxiliary class to keep static data
properties
Data1
Data2
end
end
classdef UseData % main class
properties (Constant)
Data = SharedData
end
% Class code here
end
and then we can use it with something like this:
k = UseData
k.Data.Data1=5; % Want to be `k.Data1=5;` instead.
BUT I'm looking to have a top-level static member
( something like
obj_of_UseData.Data1=5;
NOT
obj_of_UseData.Data.Data1=5; )
(i.e. like a top-level member, not second-level one). I seek a method to implement top-level static member , not second-level one.
Thanks
It is possible to follow the advice from the MathWorks related to static data, and still create behavior that makes it look like those variables are members. You can do so by overloading the subsref and subsasgn methods like below. This codes uses the static method way of creating static data, since it is simplest, but the idea translates to the other method, using a handle class, as well.
classdef UseData
properties
Data3
end
methods (Static)
function out = setgetVar(name,value)
persistent data;
if isempty(data)
data = struct('Data1',[],'Data2',[]);
end
if nargin==2
data.(name) = value;
end
out = data.(name);
end
end
methods
function obj = subsref(obj,S)
if isequal(S(1).type,'.')
if strcmp(S(1).subs,'Data1') || strcmp(S(1).subs,'Data2')
obj = UseData.setgetVar(S(1).subs);
return
end
end
obj = builtin('subsref',obj,S);
end
function obj = subsasgn(obj,S,value)
if isequal(S(1).type,'.')
if strcmp(S(1).subs,'Data1') || strcmp(S(1).subs,'Data2')
UseData.setgetVar(S(1).subs,value);
return
end
end
obj = builtin('subsasgn',obj,S,value);
end
end
end
To see it working:
>> x = UseData;
>> y = UseData;
>> x.Data1 = 'bla';
>> y.Data2 = [5,6];
>> x.Data3 = 0;
>> y.Data3 = 10;
>> y.Data1
ans = bla
>> x.Data2
ans =
5 6
>> x.Data3
ans = 0
>> y.Data3
ans = 10
I am trying make a simple agent and environment class in MATLAB 2014.
I am trying to have the object 'a' of Agent class as one of the properties of the Environment class. I have initialized the object in the Environment class constructor, but whenever I am trying the access the methods of Agent class using this object A, I am getting warning as:
"Confusing function call. Did you mean to reference property 'a'?"
Here is my Environment class and Agent class. How do I call method of Agent class from interact_with_agent_function directly like we call in JAVA?
classdef Environment < handle
properties (Constant = true)
V = 0.5;
T = 1;
end
properties (SetObservable= true)
A;
B;
a;
end
methods
function obj = initialize(obj, A, B)
obj.A = A;
obj.B = B;
a = Agent();
end
function act = call_agent(obj)
act = agent_function(a, obj.A, obj.B, obj.V, obj.T);
end
function action = interact_with_agent(obj)
action = obj.call_agent();
end
end
end
classdef Agent < handle
properties (SetObservable = true)
action;
end
methods
function action = agent_function(obj, A, B, v, t)
obj.action = A + v * t * ((B - A) / norm(B - A));
action = obj.action;
end
end
end
The problem here is as follows:
in the class definition, you created a variable (property) of your Environment class: lowercase a
in the initialize method, you create a local variable a, which is removed after the function finished. You should use obj.a = ... to save the Agent() in the object.
in the call_agent you use an uninitialised local variable a as first input. If you mean to refer to the a property of your class; use obj.a instead
On top of that, it might be useful to know that matlab has a default initialisation function for it's classes, which matches the name of your class; in your case this would be function obj = Agent(obj) and function obj = Environment(obj); see also https://nl.mathworks.com/help/matlab/object-oriented-programming.html for more information on classes in matlab.
You should define your classes this way:
classdef Environment < handle
properties (Constant = true)
V = 0.5;
T = 1;
end
properties (SetObservable= true)
A;
B;
a;
end
methods
% Replace here the init function using the Matlab Constructor
function obj = Environment(obj, A, B)
obj.A = A;
obj.B = B;
obj.a = Agent(); % Call the Agent constructor here
end
function act = call_agent(obj)
% Calling agent_function will automatically put a as the first argument
act = obj.a.agent_function(obj.A, obj.B, obj.V, obj.T);
end
function action = interact_with_agent(obj)
action = obj.call_agent();
end
end
end
classdef Agent < handle
properties (SetObservable = true)
action;
end
methods
% Create Constructor
function obj = Agent()
obj.action = [];
end
function action = agent_function(obj, A, B, v, t)
obj.action = A + v * t * ((B - A) / norm(B - A));
action = obj.action;
end
end
end
I don't know why you are using two function to use the property a.
It is possible to call the function agent_function directly in the function interact_with_agent.
Anyway if you really want to code this way, you should set the function call_agent as static using: methods (Static, Access = private). Like this, the only way to access to the property a will be to use the function interact_with_agent
suppose we have following class,i want to declare rational number class in matlab,i am beginner of object oriented programming in matlab languages and i want to learn basics
classdef ratnum %rational number class
properties (Access=protected)
n %numerator
d %denomerator
end
methods
function r=ratnum(numerator,denomenator)
r.n=numerator;
r.d=denomenator;
end
end
end
how can i create constructor with specific values in matlab main part?should i use name of class ?thanks in advance
To instantiate an object of this class you can use: num1 = ratnum(2,3)
Since MATLAB doesn't have method overloading that is based on the amount of passed inputs, you could use nargin to select the correct scenario, as follows:
classdef ratnum %rational number class
properties (Access=protected)
n %//numerator
d %//denominator
end
methods
function r = ratnum(numerator,denominator)
switch nargin
case 2
r.n=numerator;
r.d=denominator;
case 0
%//whatever you want the defaults to be
end
end
end
end
A simple debug trick is to do num1_str=struct(num1) which allows you to see the contents of the object. However, you should create some public methods to get the values (instead of turning the object to a struct every time).
To overload the default summation of MATLAB you need to understand that whenever you write a+b it is automatically translated into plus(a,b). When defining custom classes with custom summation you should make a folder that has the name #classname (in your case #ratnum) and in it:
ratnum.m: the class definition file (which is the code you wrote)
a file named plus.m which looks something like:
.
function sum = plus(ratnum1,ratnum2)
ratnum1 = ratnum(ratnum1);
ratnum2 = ratnum(ratnum2);
sum = (...
ratnum1.r*ratnum2.d + ...
ratnum2.r*ratnum1.d )/ ...
(ratnum1.d * ratnum2.d);
end
Then, when you use + to add ratnums it will use the correct plus function.
Here's some helpful reading: MATLAB Documntation: Implementing Operators for Your Class
To call class methods, even from within other class methods, you must always write the class name first: ratnum.sum(ratnum1). Here's an example:
classdef ratnum %rational number class
properties (Access=public)
n %//numerator
d %//denominator
end
methods (Access = public)
function r = ratnum(numerator,denominator)
switch nargin
case 2
r.n=numerator;
r.d=denominator;
case 0
%whatever you want the defaults to be
end
end
end
methods (Access = public, Static)
function out = sum(ratnum)
out = ratnum.n + ratnum.d;
end
end
end
then:
>> a = ratnum(1,1)
a =
ratnum with properties:
n: 1
d: 1
>> ratnum.sum(a)
ans =
2
If you want to overload constructor with many different forms you'll have to initialize missing parameters with default value (or use varargin for more complex overloads):
function [r] = ratnum(num, den, varargin)
% Showing initializing missing parameters
if (nargin < 2), den = 42; end
if (nargin < 1), num = 7; end
% Showing working with varargin
if (nargin == 3)
...
elseif((nargin > 1) && (ischar(varargin{1}))
...
else
...
end
end
If you want to create named initializers for clarification of their meaning, you'll have to do it with Static methods:
methods (Static)
function [r] = TwoThird()
r = ratnum(2, 3);
end
function [r] = Half()
r = ratnum(1, 2);
end
end
Which can be used like this:
dummy = ratnum.Half(); % Ratio is 1/2
dummy = ratnum.TwoThird(); % Ratio is 2/3
dummy = ratnum(42, 666); % Ratio can be any custom one
If I run this code to create a simple class:
classdef myclass
properties
m = 2;
n = m + 2;
end
end
I get an error:
Undefined function or variable 'm'.
Error in myclass (line 1)
classdef myclass
Why is this? I left out the constructor in this minimal example because a) the error still occurs if I put the constructor in, and b) I encountered this error in a unit testing class, and the constructor isn't called in such classes in MATLAB 2013b.
There is a note on this page that might explain the problem:
Note: Evaluation of property default values occurs only when the value is first needed, and only once when MATLAB first initializes the class. MATLAB does not reevaluate the expression each time you create a class instance.
I take this to mean that when you create a class instance, m is not yet initialized, hence you cannot use it to set the default for another property n.
The only way I can get it to work is if I declare m as a Constant property:
classdef myclass
properties (Constant = true)
m=2;
end
properties
n = myclass.m + 2;
end
end
But that probably doesn't help if you want to change m.
You could also move the initialization to the constructor:
classdef myclass
properties
m = 2;
n;
end
methods
function obj = myclass(obj)
obj.n = obj.m + 2;
end
end
end
MATLAB defines the properties as classname.propertyname. Hence, if you change the code to the following, it should work.
classdef myclass
properties
m = 2;
n = myclass.m + 2;
end
end
Kind regards,