How to modify properties of a Matlab Object [duplicate] - matlab

This question already has answers here:
How do properties work in Object Oriented MATLAB?
(3 answers)
Closed 3 years ago.
I've created a MATLAB class, something like:
classdef myclass
properties
x_array = [];
end
methods
function increment(obj,value)
obj.x_array = [obj.x_array ; value);
end
end
end
The problem is, the property x_array is never modified when I invoke the increment() function:
ex:
>>s = myclass
>>increment(s,5)
>>s.x_array
ans = []
I did some research, and I reached a conclusion that this is because of MATLAB using Lazy Copy for objects, making my class inherit the HANDLE class should have solved this, but it didn't, does anybody know why this is happening? And if extending the handle class is indeen the solution, isn't this the right way to do it:
classdef myclass < handle
or are there any extra steps?

This is similar to this question. In short all you should have to do is inherit from handle class.
Quick example
Contents of file myclass.m
classdef myclass<handle
properties
x_array = []
end
methods
function obj=increment(obj,val)
obj.x_array=[obj.x_array val];
end
end
end
Now from the Matlab command prompt, you can do the following
>> s=myclass;
>> s.increment(5)
>> s.increment(6)
>> s
s =
myclass handle
properties:
x_array: [5 6]
lists of methods, events, superclasses

There is an easier way. You only need to overwrite your initial instance s as follows:
s = increment(s,5);
More information in the documentation.
PS: While it is fine to use handle, the way copy function works is different and you should be careful about the way you use it. When you use handle, in fact you are making a new address/reference to an obj

Related

Passing variable to a class in MATLAB

It is my first time asking a question here and I am quite new to MATLAB. So, I am sorry in advance if my explanation is faulty or insufficient. I'll be happy to hear any advice to improve myself.
I would like to create a class which has an array of a certain size. Let's call this class 'MyClass'. My class is as follows:
classdef MyClass
properties
A = array2table(zeros(ArraySize,1));
end
end
The variable ArraySize is defined in my main.m file and i want to create an object from this class within the same file:
ArraySize = 10;
MyObject = MyClass;
However, the class I created does not recognize the ArraySize variable. Could somebody tell me if there is an easy way to achieve this?
So far, I tried to make it a global variable, I tried using 'load' function to pass parameters between files. I tried defining the class inside a function. None of them seem to work. I read about 'handles' in forums and i got the idea that it somehow can be related to the solution of my problem, but I do not really know how to work with them. What I understood so far is that handles correspond to pointers in C++. I would like to know if they can be used to solve my problem and if so, how exactly.
Thanks in advance.
You should just write your constructor to accept ArraySize as an input argument and then initialize the value A inside of your constructor.
classdef MyClass
properties
A
end
methods
function self = MyClass(arraySize)
self.A = array2table(zeros(arraySize,1));
end
end
end
And then instantiate your class
myObject = MyClass(ArraySize);
And with regards to handle classes, check out this page of the documentation to see recommendations on when to use handle and value classes.

Save custom objects as struct in matlab

Data tends to survive longer than code. So I want to save my objects as struct.
The idea is to overwrite the saveobj method calling struct recursively on itself.
classdef foo < handle
properties
Data = 12
end
methods
function data = saveobj(o)
data = struct(o);
end
end
end
I now call:
>> bar = foo;
>> save('test', 'bar')
>> bar2 = load('test')
>> class(bar2.bar)
'foo'
However the saved object is still of type foo. Any help figuring out where I screwed up would be appreciated. Thanks
In case it matters I'm using R2012a on RHLE6
The "problem" is that despite the documentation implying that the output from saveobj gets saved with no knowledge that it originated from an object, that is not the case. The structure knows that it came from an object, and when loaded will get passed to a loadobj method if it exists, or the constructor if it doesn't.
One way to overcome this is to overload save, and then call save on the struct within the save method of the object; another is to have a method that returns a struct and then call save on that struct. There are probably also some hacks that can be done to make it a little more automatic, which is most likely what you really want.
I found a truly ugly hack-around, which might help somebody. Due to its ugliness I will however still wait for an answer.
As Phil already pointed out is the class name still stored with the file. However we can trick matlab with an other file with the same name.
My original class looks like this:
classdef foo < handle
%// This is the original class used to some stuff and it holds
%// important data. But I lost it over time...
properties
Data = 12
end
methods
function data = saveobj(o)
for f = properties(o)'
data.(f{1}) = saveobj(o.(f{1}));
end
end
end
end
Now, since I assume I don't have the original source anymore I can use a dummy class to load the data.
classdef foo < handle
%// This is the pretender class source. Since I lost the source of
%// the original class.
methods (Static)
function data = loadobj(data)
global DATA
DATA = data;
end
end
end
The load will naturally fail, but I can extract the struct feed into the loadobj method by calling:
global DATA
As I said a very ugly solution. That's why I'll wait till somebody smart comes around and finds a better way to solve this problem, but I thought I post it in case it helps somebody.
Another hack-around might be to save the class-code while saving the object.
For loading the object of your class, you could first load the code, store it as a m-file and then load the object of the class.

implementing abstract methods in matlab

I'm new to MATLAB OOP. I have an abstract class defining an abstract method in my matlab path. I have a subclass named SubAbsClass in a subfolder named #SubAbsClass. I cannot create an object of the subclass after implementing the abstract method in the subclass. Here's my SubAbsClass implementation:
classdef SubAbsClass < AbsClass
properties
O1
end
methods
function obj=SubAbsClass(a,b)
obj.O1=absMethod(a,b);
end
end
methods (Static)
function out = absMethod(a,b)
out = a + b;
end
end
end
and my abstract class implementation is:
classdef AbsClass
methods(Abstract, Static)
result = absMethod
end
end
when I try to create an object in the MATLAB path (the abstract class is in the MATLAB path), I get an error. I have tried many configurations and searched the matlab oop document, and also the web including stackoverflow but unfortunately couldn't find an example to implement. I appreciate your help
>> clear all; clear classes;
>> obj=SubAbsClass(5,2)
Undefined function 'absMethod' for input arguments of type 'double'.
Error in SubAbsClass (line 11)
obj.O1=absMethod(a,b);
Within a method, Matlab considers non-dot references to be calls to local functions (defined outside the classdef block within the class file) or to a function somewhere on the Matlab path following the usual look-up rules.
So you need to call the Static method via the instance obj in the constructor:
methods
function obj = SubAbsClass(a,b)
obj.O1 = obj.absMethod(a,b);
end
end
One little caveat to the above is that non-Static methods also have a functional form.
So if the method was not Static, this notation would also work
methods
function obj = SubAbsClass(a,b)
obj.O1 = absMethod(obj,a,b);
end
end
Which, I think, is almost equivalent to the dot notation, although it has been said to be "generally" faster (albeit, that was four years ago).
Here are the details for ordinary method invocation and Static method invocation.

Add elements to matlab cell array member variable

i have a class called sampleClass with a cell array member variable called list.
Now i am trying to add elements to the internal list. For this purpose, i created the method addToList. The method simply tries to add elements to the list.
classdef sampleClass
properties
list = {}
end
methods
function addToList(obj)
obj.list{end+1}='test';
obj.list
end
end
end
Now the problem is, that the elements are not stored in the list.
Inside the function addToList the following output signalizes that the element is stored in the list:
>> samp = sampleClass();
>> samp.addToList
ans =
'test'
But after leaving the function, the element is no longer accessible:
>> samp.list
ans =
{}
Has anybody an idea what's going wrong? I am using Matlab 7.11.0 (R2010b).
Thanks for your help.
Julien
That's because you forgot to inherit from the handle class:
classdef sampleClass < handle %// Change here!
properties
list = {}
end
methods
function addToList(obj)
obj.list{end+1}='test';
obj.list
end
end
end
If you want to retain the changes made when modifying an instance of your class, you must inherit from the handle class. This can be done by taking your class definition (first line of your code), and doing < handle. If you don't, then any changes you make will not be saved. To show that this works, this is what I get in MATLAB:
>> samp = sampleClass();
>> samp.addToList
ans =
'test'
>> samp.list
ans =
'test'
To be more verbose, here's what the MATLAB docs say about handle:
The handle class is the superclass for all classes that follow handle semantics. A handle is a reference to an object. If you copy an object's handle, MATLABĀ® copies only the handle and both the original and copy refer to the same object data. If a function modifies a handle object passed as an input argument, the modification affects the original input object.
As such, you need to inherit from the handle class so that you have a reference back to the object you created. Any changes you make to the instance of your class will be remembered if you inherit from handle. If you don't, no changes you make get registered.

Why does my MATLAB (R2008a) object's class change on a save/load cycle?

UPDATE:
This is a known bug - link requires a login to Mathworks to access it.
Summary of bug report
An instance of a MATLAB user-defined
class saved to a MAT file using
Version 7.6 (R2008a) might not load
properly if one of its property values
is an instance of a different MATLAB
class.
Briefly, Mathworks reports that a previously saved top level custom object may be loaded incorrectly (as described below) and that the error occurs on the SAVE step. So, the data is corrupted inside the MAT file.
From my experience this seems to be intermittent. In one data analysis application I wrote out of 75 MAT files 37 were saved with this corruption :(
Be careful with user defined objects. I added the following test on save to make sure that the data is not corrupted
save('MAT_file_name.mat');
tmp=load('MAT_file_name.mat');
if ~isa(tmp.bb,'superClass')
msgbox({'THE FILE WAS NOT SAVED PROPERLY', ...
' ', ...
[' MAT_file_name.mat',]})
end
Orginal Question
Here I am using MATLAB 2008a. This subtle bug is fixed in MATLAB-2009a.
Anyway, the way my two classes are defined, the save/load cycle causes the variables of one class (superClass) to be loaded as variables of my second class (propClass).
Example MATLAB (r2008a) Session
>> bb=superClass;
>> whos
Name Size Bytes Class Attributes
bb 1x1 60 superClass
>> save
>> clear
>> clear classes
>> load
>> whos
Name Size Bytes Class Attributes
bb 1x1 60 propClass
After loading matlab.mat, the variable bb has mysteriously changed from superClass to propClass
Class: superClass
This class needs to contain an array of type propClass and here is it's Naive definition
classdef superClass<handle
properties(SetAccess=private)
a = propClass.empty % need to set this property as type propClass
% otherwise the addProp method throws an error
count=0;
end
methods
function self=superClass
%empty class definitionS
end
function addProp(self)
p = propClass;
self.count = self.count+1;
self.a(self.count)=p;
end
end
end
Class: propClass
PropClass is a second class used by the super class. Its definition is not important for this bug.
Question
So, why is superClass being changed to propClass after the load operation in MATLAB-R2008a? Secondly, how can I change the definition of superClass to avoid this symptom?
Note
I ran into this symptom in a larger class I had written and narrowed down the source of the problem. I know it occurs in the MATLAB session described above but it seems that if I add an object to the property array in superClass then the problem disappears.
So, if I call superClass.addProp before saving then the strange change from superClass to propClass doesn't occur.
That's a strange problem! I haven't come across anything like that, but one thing you could try first is to move the initializations of the properties to the constructor:
classdef superClass < handle
properties (SetAccess = private)
a
count
end
methods
function self = superClass
self.a = propClass.empty;
self.count = 0;
end
function addProp(self)
p = propClass;
self.count = self.count+1;
self.a(self.count) = p;
end
end
end
I'm not sure it will have any effect, but that's the only thing I can think of to try. Hope it helps! =)