How can I find out whether a property is inherited from a super class or is defined in the class definition directly? Assuming obj is an instance of the class, I have tried:
properties(obj)
metaclass(obj)
metaclass returns a meta.class object that contains information about the class that is queried. The useful property of this meta.class object is the PropertyList, which contains information about all the properties of the class, including the DefiningClass.
Using the following class definitions as an example:
classdef asuperclass
properties
thesuperproperty
end
end
and
classdef aclass < asuperclass
properties
theclassproperty
end
end
We can now query the properties of aclass to determine where they came from:
tmp = ?aclass;
fprintf('Class Properties: %s, %s\n', tmp.PropertyList.Name)
fprintf('''theclassproperty'' defined by: %s\n', tmp.PropertyList(1).DefiningClass.Name)
fprintf('''thesuperproperty'' defined by: %s\n', tmp.PropertyList(2).DefiningClass.Name)
Which returns:
Class Properties: theclassproperty, thesuperproperty
'theclassproperty' defined by: aclass
'thesuperproperty' defined by: asuperclass
You can wrap this into a simple helper function. For example:
function classStr = definedby(obj, queryproperty)
tmp = metaclass(obj);
idx = find(ismember({tmp.PropertyList.Name}, queryproperty), 1); % Only find first match
% Simple error check
if idx
classStr = tmp.PropertyList(idx).DefiningClass.Name;
else
error('Property ''%s'' is not a valid property of %s', queryproperty, tmp.Name)
end
end
Related
In Matlab I have the package "+mypackage". All the following definitions are under this folder/package.
MyClass.m
classdef MyClass
properties
prop1 MyProperty
end
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.prop1 = mypackage.MyProperty(num);
end
end
end
MyProperty.m
classdef MyProperty
properties
num double
end
methods
function obj = MyProperty(val)
obj.num = val;
end
end
end
So in MyClass.m I define the prop1 property to be an object of class MyProperty.
Now I would like to create objects with this script.
import mypackage.MyClass
class_test1 = MyClass(5);
class_test2 = MyClass.with_five();
When I run it I get following errors:
Error using Testpackage (line 3)
Error defining property 'prop1' of class 'mypackage.MyClass':
Class named 'MyProperty' is undefined or does not support property validation.
When I remove the property definition from MyClass.m it works.
Is there a way to define properties to be an object of an own class in Matlab?
Thank you Wolfie your Help!
I changed the definition for prop1 to mypackage.MyProperty.
My Class definition looks now like this:
classdef MyClass
properties
prop1 mypackage.MyProperty
end
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.prop1 = mypackage.MyProperty(num);
end
end
end
Its necessary to point to MyProperty inside my package mypackage.
Otherwise Matlab is not able to find it.
I found it in the Matlab help:
https://de.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html?s_tid=srchtitle#brfynt_-3
I've made a mistake and recorded a bunch of important data using a class definition that I can't find anymore. The methods are not important, I just want the data; a struct conversion would be fine.
Is there any way I can recover this?
Googling it did not help.
The solution is to create a new class that overloads the loadobj method. See here for more information regarding the load process for classes.
I replicated your problem by creating a class:
classdef myclass
properties
Prop1
Prop2
Prop3
end
methods
function obj = myclass(a,b,c)
obj.Prop1 = a;
obj.Prop2 = b;
obj.Prop3 = c;
end
end
end
Then I created an object of this class and saving it to a file "x.mat":
x = myclass('a',56,[1,2,3]);
save x
Next, I deleted the myclass file and did clear classes. This put me in your situation.
I then created a new myclass class that overloads the loadobj method:
classdef myclass
properties
data
end
methods (Static)
function obj = loadobj(s)
obj = myclass;
obj.data = s;
end
end
end
Note how it doesn't know any of the original properties. This does not matter. If any of the original properties is missing when loading an object from a MAT-file, loadobj will be called with s being a struct containing all the properties of the original object.
With this new class definition, load x created an object x of class myclass, where x.data was a struct containing the properties of the object saved in "x.mat".
I have a simple data loading class:
classdef DataLoader
properties
data;
end
methods
function obj = loadData(obj, file)
obj.data = csvread(file);
end
end
end
After the data is loaded, I can see that the object reports the data is in:
s = DataLoader();
s.loadData('data.csv')
ans =
DataLoader with properties:
data: [8738102×8 double]
However, when I access the data:
s.data
ans =
[]
Furthermore, after this access:
s =
DataLoader with properties:
data: []
EDIT: so I've solved my problem:
s = s.loadData('data.csv');
but is there a way to do just:
s.loadData('data.csv');
As you discovered already, you have to overwrite your old object with the new object returned by loadData, since your class is a value class. If you want your object to have reference-like behavior, it needs to inherit from the handle class. This is what your new class code will look like:
classdef DataLoader < handle % Inherit from handle class
properties
data;
end
methods
function loadData(obj, file) % No need to return output now
obj.data = csvread(file);
end
end
end
Now you can use the following syntax:
s.loadData('data.csv');
I have an object from my own class object that inherits from my own class data and my own class graphic in MATLAB. To represent the object object, it uses properties and methods from the data-superclass. Now I want to draw my object object with methods from the graphic-superclass, but the methods in this superclass don't know anything about its object-subclass.
Is there a way to give the required data, that is stored in the object-subclass, to the graphic-superclass without putting this information into a function argument like object.draw(this_data_stuff) with the method drawfrom the graphic-superclass and the data this_data_stuff from the object-subclass?
The only way I figured out is to store the subclass object object as property in the graphic-superclass, but it seems odd to store a subclass-object as property in a superclass-object, while the subclass inherits from the same superclass.
EDIT:
data-class:
classdef data < handle
properties
data_stuff
end
methods
function obj = data
end
function obj = compute(obj)
obj.data_stuff = ... % math
end
end
end
graphic-class:
classdef graphic < handle
properties
end
methods
function obj = graphic
end
function obj = draw(obj)
plot(obj.data_stuff,t) % ERROR, property 'data_stuff' is unknown
end
end
end
object-class:
classdef object < data & graphic
properties
end
methods
function obj = object
end
end
end
Test:
object_A = object; % creates object
object_A.compute; % generates data_stuff
object_A.draw; % draws data_stuff, Error here, because 'draw` needs access to the 'data_stuff'-property.
As you know we can define class definition and method definition in separate files in #folder. How we can do that if we have attributes for method? I read in MATLAB OOP documentation that we should use this structure in method file:
classdef myClass
method (att = value,...)
tdata = testdata(obj,arg1,arg2)
end
end
But we have another file (myClass) in this folder for class definition so if we have this structure we have two class definition files. one of them has properties definition and another has methods properties (two files with same name!). If we change above classdef name(myClass) to function name(testdata), we have a error in MATLAB. What should I do?
If you're defining your class using an #-folder and separate files, you don't need two class definition files. You need a single class definition file (which is basically as you've defined in your question) and a separate file that contains just your method, implemented as a function.
For example:
#MyClass\MyClass.m
classdef MyClass
properties (GetAccess = public, SetAccess = private)
myGreeting
end
methods (Access = public)
function obj = MyClass
obj.myGreeting= 'hello'
end
function sayhello(obj, name)
txt = obj.getText(name);
disp(txt)
end
end
methods (Access = private)
txt = getText(obj, name)
end
end
#MyClass\getText.m
function txt = getText(obj, name)
txt = [obj.myGreeting, ' ', name];
end
Note that you only need to include the stub definition of the method within the class definition file if you need to modify the method attributes from default. If it's a public method (and non-Static, non-Hidden, non-Sealed, non-Abstract etc), you don't need to include it at all, you just need to include the file in the #-folder.