I am having some issues with matlab now that I have added a new variable to a class.
I have tried using clear classes as the error message says to but this seems to still produce the same message. I have also tried every clear command possible, rehash commands, restarting matlab and am now completely out of ideas..
Don't suppose anyone else has any? I'm using matlab 2013b if that's any use!
Cheers!
Since you're not providing much info, let me show what I get with a simple example running on R2014a. Consider the following class:
MyClass.m
classdef MyClass
properties
x
end
end
First I create an object of this class:
>> a = MyClass()
a =
MyClass with properties:
x: []
Next I modify the above by adding a new property y, and saving the MyClass.m file:
MyClass.m (after change)
classdef MyClass
properties
x
y %# <-- added
end
end
Now if I try to create another instance of the class, I get the following warning:
>> b = MyClass()
Warning: The class file for 'MyClass' has been changed, but the change cannot be applied because objects
based on the old class file still exist. If you use those objects, you might get unexpected results. You
can use the 'clear' command to remove those objects. See 'help clear' for information on how to remove
those objects.
b =
MyClass with properties:
x: []
As indicated, we won't see the changes until we clear all instances of the old class:
>> whos
Name Size Bytes Class Attributes
a 1x1 104 MyClass
b 1x1 104 MyClass
>> clear classes
>> whos
>> b = MyClass()
b =
MyClass with properties:
x: []
y: []
Now the modifications are picked up by the new object.
Note that in some cases, MATLAB might still hold references to objects not visible in the base workspace (like if you have globals, locked functions, or GUIs with data saved in the app/user data section of the GUI). Usually closing all figures and clearing all variables will remedy the situation. If not, restarting MATLAB will most definitely get could back to a clean slate.
Related
I defined a class in one of my many MATLAB packages. To my suprise, I could not access a constant property of my class without importing the class definition. Even if it is a method of the class itself. Like so:
classdef TestClass
properties( Constant )
c=0;
end
methods
function obj = TestClass()
end
function getC(obj)
import test.TestClass;
disp(TestClass.c);
end
end
end
I just want to check whether I am doing something wrong here or is this the correct way to use constants in MATLAB.
Since you have placed TestClass inside a package Matlab needs to know where to look to find the definition for this class, even if it's a reference from within the class or function. An alternate to the above code could be:
function getC(obj)
disp(test.TestClass.c);
end
Alternately, if within a class, constant values can be accessed from the object itself.
function getC(obj)
disp(obj.c);
end
If neither of these is working for you, you may need to refresh the classdef for TestClass from memory. This will cause matlab to reload the constant value, which is pulled into Matlab when it first parses the classdef file to determine the structure of the class. This can be done using clear classes, however a warning that it will also clear all other classes, variables, and any breakpoints you have set.
If you want to see if this is necessary you can view the metaclass object to determine what Matlab "thinks" your class structure should be. You can do this using the following.
mc = ?test.TestClass;
mc.PropertyList
You may need to index into the property list to find the specific property you are interested in, but the thing you are looking for are the following fields.
Name: 'c'
Constant: 1
DefaultValue: 0
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.
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.
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
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! =)