Access data in subclass from superclass - matlab

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.

Related

Variable YYY originally saved as a XXX cannot be instantiated as an object and will be read in as a uint32

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".

Finding inheritance property of a matlab class method

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

Force conversion of struct to object in MATLAB loadobj function

I am working with a custom defined class I called "PathObj_Standard". I want to make sure that when I load this class, if the property CalcDate was saved as a cell array it is converted to a standard array. However, I changed the class definition some time ago, so when I use the loadobj function, I am getting a struct instead of an object. The original code I'm using has a lot more properties, so I'd rather not create a new object by assigning property by property from the struct to a new object. Furthermore, I'm also hesitant to change the constructor to accept a struct as an argument.
I tried using the class function inside loadobj, but I am getting a Cannot redefine class 'PathObj_Standard' without a call to 'clear classes' error. Isn't this function supposed to force conversion of a struct to an object? Why doesn't it work within the loadobj function?
classdef PathObj_Standard < handle
properties (SetAccess = protected)
CalcDate;
Name;
end
methods(Static)
function obj=loadobj(s)
if isstruct(s)
obj=class(s,'PathObj_Standard');
else
obj=s;
end
if not(isempty(obj.CalcDate)) && iscell(obj.CalcDate)
obj.CalcDate=cell2mat(obj.CalcDate);
end
end
end
methods
function obj=PathObj_Standard(Name,CalcDate)
obj.Name=Name;
obj.CalcDate=CalcDate;
end
end
The issue is that calling class attempts to create a class which you can't do from within your loadobj. You'll want to call the actual constructor
Also in my experience, the easiest way to construct a class from a struct is to inherit from hgsetget rather than handle as that automatically has the set and get methods of MATLAB's graphics objects and these methods can accept property/values in the form of a struct. In newer versions of MATLAB, you can also use the SetGet mixin
classdef PathObj_Standard < hgsetget
If you do this, you could change your loadobj method to be something like
function obj = loadobj(s)
% Update the input struct as needed
if isfield(s, 'CalcDate') && ~isempty(s.CalcDate) && iscell(s.CalcDate)
s.CalcDate = cell2mat(s.CalcDate);
end
% Call the default constructor
obj = PathObj_Standard();
% Update all properties that were supplied to loadobj
set(obj, s)
end

MatLab OOP Setting a Property via a Utility Method

I'm trying to change a property in a class called houses via a utility method which is Static. I'm getting terribly confused with the reference obj as I don't know when and where it should be used. I am trying to bypass the constructor method so I can access the setProperty method, but I am getting errors such as too many output arguments. I've tried passing in obj as well as x, but I get similar errors. However, I can change the property a if I pass in a value to the constructor method.
classdef houses
properties
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
obj.a = x;
end
end
end
In general, you should not use static methods to set properties of a class. If your property is public, then you can use a static method but it is highly recommended that you do not. If your property is private/protected, then you definitely cannot use a static method to modify it.
Your class should look like this then (I took the liberty of stating explicitly the access properties of each block):
classdef houses
properties (Access = private)
a;
end
methods (Access = public)
% constructor method
function obj = houses()
end
function SetA(obj, a)
obj.a = a;
end
function DoSomething(obj, more_parameters)
% Lengthy stuff here
end
end
end
Now, regarding your question about obj: the answer is you must pass obj as the first argument of every instance method. The variable obj refers to the current instance of the class in a generic way. See for example the method DoSomething.
Static methods do not have access to any of the properties of the class, unless public. As such, when declaring a static method, you should not pass the obj variable.
Last thing: always use explicit access modifiers for your properties and methods. It will save you some headaches.
A static method is not typically supposed to access an object (hence it does not have access to obj).
If you want to modify a static propperty (shared by all objects, and the class itself), you can use something like:
classdef houses
properties (Static)
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
houses.a = x;
end
end
end
Regarding obj, it is the 1st argument of every methods (non static). So when you do:
o = myClass();
o.myMethod(args);
Matlab will see this as:
myMethod(o, args);
So when you define the method, you have to put obj as the 1st argument (in fact you can choose any name, it does not have to be obj).

create array of objects of a class in another class MATLAB

I am trying to create an array of objects of a class Cell in another class Systemin MATLAB. The classCell` is:
classdef Cell
properties
ID;
EntityID;
ZoneID;
NeighborID;
State;
nextChangeTime;
end
methods
% Define the constructor
function obj = Cell()
obj.ID = zeros(1);
obj.EntityID = zeros(1);
obj.ZoneID = zeros(1);
obj.NeighborID = zeros(1);
obj.State = zeros(1);
obj.nextChangeTime = zeros(1);
end
end
Now I have another class System. I try to make an array of Cell objects like this:
classdef System
properties
Cells;
end
methods
function obj = System(dimx,dimy)
obj.Cells(dimx,dimy) = Cell();
end
end
But I think I am using the wrong format. Not sure if this is possible. Any suggestions on how to accomplish this would be appreciated.
In order to be able to create arrays of objects of user-defined class (e.g. Cell class), it is convenient to have the default constructor for the user-defined class. The default constructor is the one that takes no arguments (i.e. when nargin==0). When creating arrays, the implicit initialization of the array's objects is done by this constructor. If this constructor is missing, trying to build arrays by "extending" a scalar object will generate an error.
Another way of creating arrays of objects (without defining a default constructor) is by using horzcat, vertcat and cat.
Aaaaand... when accessing the properties of an object, don't forget to mention the object you're accessing:
obj.Cells = Cell.empty(0,0); % Force the type of empty Cells to Cell class
obj.Cells(dimx,dimy) = Cell();