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.
Related
I tried to change an attribute value of a class by invoking one of its member function:
p1 = tank();
p1.checkOri(p1);
And in the class definition, I have that static method:
classdef tank
properties
value
...
end
methods
...
methods (Static)
function obj = checkOri(obj)
if (CONDITION) %the thing I want it to do
obj.value = EXPRESSION;
...
Yet this checkOri method is not working. But if I write this method in the main file, or to say altering the value of p1-the instance of class tank-it works perfectly:
p1 = tank();
p1.checkOri(p1);
if (CONDITION) %the thing I want it to do
p1.value = EXPRESSION;
It works perfectly.
I wonder what caused this. From my experience with other programming languages, invoking method should have worked, is it because of some tricks with Matlab syntax or static method? How could I fix it so that this method would work?
So, as #Navan in the comment said, handle class could be a solution.
It appears Matlab has a similar parameter concept with Java and C++, arguments modified in a function/method only remains that modification inside the function/method.
For this class, I simply added < handle in the head of class definition and it worked:
classdef tank < handle
properties
...
But I am not sure if that is the only solution, there might be better ways to do this. So I'll leave that question open, you are more than welcomed to post your opinion:D
In MATLAB, the call
p1.checkOri();
is equivalent to
checkOri(p1);
In both cases, the class method checkOri is called for the class of object p1, passing p1 as first argument to the function by value.
Because p1 is passed by value, any changes made to it inside the function are not seen by the object in the calling workspace. Therefore, one typically does
p1 = checkOri(p1);
This way, the object that was passed by value and modified inside the function is passed back out and assigned to the variable that held the original object.
If the method is written as follows:
function obj = checkOri(obj)
%...
end
then MATLAB will optimize the above function call such that no copy of the object is actually made. Note that both in the function declaration and in the function call, the input and output variable is the same.
As already discovered by OP, the above does not hold for handle classes, classes that inherit from handle. These classes act as if they are always passed by reference, and any change made to them in any workspace will be reflected in all other copies in other workspaces.
Also assigning to a member variable does not follow the above, such that
p1.value = 0;
modifies object p1.
For more information on the difference between value classes and handle classes see this other question.
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'm having some trouble creating classes in matlab and I don't really understand the method behind it (i'm fairly new to it)
here is my attempt at basic addition using matlab
classdef test
properties
a
b
end
methods
function add = plus(a, b)
end
end
end
assigning values via
p=test(), p.a=5
etc seems to work fine, however attempting p.add returns the error
No appropriate method, property, or field add for class test.
Any help or guidance would be appretiated, thanks.
Methods are defined exactly as functions are with respect to names and outputs.
Therefore, the method is called plus, the output the method should calculate is called add, and the way you probably wanted to write the method is:
function out = add(this)
out = this.a + this.b;
end
Now you call the method as
p.add();
Say I have a MATLAB object defined in a class file
classdef foo
properties
bar
end
end
And I create a foo object
myfoo = foo();
Now I want to add another field to foo dynamically. What I want is
myfoo.newfield = 42;
but this will throw an error.
I know there is a way to dynamically add a field/property to a MATLAB object but I can't remember it or find it easily in the help. Anyone know the syntax?
Ok, found it. But it's not general, only subclasses of the dynamicprops class implement it.
This is what I remember coming across. So I suspect the general answer to this question is you can't do it.
Any class that is a subclass of the dynamicprops class (which is itself a subclass of the handle class) can define dynamic properties using the addprop method. The syntax is:
P = addprop(H,'PropertyName')