I created a class based on a list of variables that comes from data. I made a function that will place all data inside an object of this class.
As the list of variables grows, I keep having to adjust the class and the load function. I am trying to find a way that will make my load function robust against changes in the class.
Code of the Class file:
classdef CoolClass
properties
prop_a
prop_b
prop_c
end
end
The function I wrote to load this data into an object:
function [ object_name ] = loadCoolClass (data_file_name)
load(data_file_name)
% this loads the variabels:
% prop_a = 1, prop_b = 2, prop_c = 3, prop_d = 4
object_name = CoolClass;
object_name.prop_a = prop_a;
object_name.prop_b = prop_b;
object_name.prop_c = prop_c;
end
Now what I would like to have is something that if I add a variable prop_d
to the classdef file that it will immediately load it into the loadfile as well. something like this:
function [ object_name ] = loadCoolClass (data_file_name)
load(data_file_name)
% this loads the variabels:
% prop_a = 1, prop_b = 2, prop_c = 3, prop_d = 4
object_name = CoolClass
cool_properties = properties(CoolClass)
for i = 1:size(cool_properties,2)
object_name.cool_property(i) = cool_property(i)
end
end
Now I know the loop above is not valid code but I mean: check for every property if there is a variable with that name and place it in the object.
Is there a way in matlab to use a variable holding a string, as an input to load the value of the variable named after the content of the string?
Is this possible in naming content before the '=' sign Is this possible in referring to variables after the '=' sign
In my experience, the easiest way to do this is to make your class a subclass of hgsetget
. This gives you the ability to use set(obj, 'Key', value)
and get(obj, 'Key', value)
just like you would for graphics objects.
cls = CoolClass();
set(cls, 'prop_a', 1)
The second step is to specify an output to load
(rather than just dumping the data into your workspace) which will give you a struct with a field for each variable in the file. This is recommended whenver loading from a file to keep your workspace tidy.
Now, the real benefit of subclassing hgsetget
is that you can also pass a struct
of property/values to set
and get
!
classdef CoolClass < hgsetget
properties
prop_a
prop_b
end
end
Now if you have a file data.mat
that contains values for prop_a
and prop_b
you can then do this.
cls = CoolClass();
data = load('data.mat')
prop_a: 1
prop_b: 2
set(cls, data)
If you have variables in data.mat
that are not properties of your class you can easily filter these out and still use set
.
toremove = setdiff(fieldnames(data), props);
set(cls, rmfield(data, toremove);
What I personally would do would be to write a constructor that accepts the same inputs as set
(i.e. a struct or param/value pairs) and then inside of the constructor, pass them directly to set
. Also, you can implement a loadobj
method for the class which is essentially a static method that accepts a struct as input. You can do all of your validation within that method to remove unwanted fields.
classdef CoolClass < hgsetget
properties
prop_a
prop_b
end
methods
function self = CoolClass(varargin)
set(self, varargin{:});
end
end
methods (Static)
function obj = loadobj(S)
obj = CoolClass();
% Remove any invalid fields
toremove = setdiff(fieldnames(S), properties(cls));
set(obj, rmfield(S, toremmove))
end
end
end
Now you could use this class two other ways than we could previously.
cls = CoolClass(load('data.mat'));
cls = CoolClass.loadobj(load('data.mat'));