I'm trying to list classes I created in some folder in my Matlab folder - using only their name (class name)
as an example, I have a class called 'SimpleString' - and I'm aiming to instantiate an object from that class, if all I know is that its name is 'SimpleString'
So in realtime, I'd like to find out what classes are in a folder (done), then be able to instantiate any of those classes (my question) Thanks
You can use the WHAT function to discover classes (as well as functions,packages,etc...) in a certain folder, then call METHODS to find the signature of the constructor of the class (some parsing needed here), finally using FEVAL (passing arguments if any) to create an object from this class.
You could also use meta.class to get all sorts of meta-information about your classes.
Here is some code to illustrate what I had in mind:
%# folder containing your classes
pathName = fullfile(pwd,'folder');
%# make sure it is on the path
p = textscan(path, '%s', 'Delimiter',';'); p=p{1};
if ~any(ismember(p,pathName))
addpath(pathName)
end
%# list MATLAB files
w = what(pathName);
%# get class names
fNames = cellfun(@(s) s(1:end-2), w.m, 'Uni',false); %# remove .m extension
fNames = [fNames ; w.classes]; %# add classes in @-folders
%# get classes metadata
mt = cellfun(@meta.class.fromName, fNames, 'Uni',false); %# get meta-data
mt = mt( ~cellfun(@isempty,mt) ); %# get rid of plain functions
%# build object from each class
objects = cell(numel(mt),1);
for i=1:numel(mt)
%# get contructor function
ctorMT = findobj(mt{i}.MethodList, 'Access','public', 'Name',mt{i}.Name);
%# get number of contructor arguments
numArgs = numel(ctorMT.InputNames);
%# create list of arguments (using just zeros)
args = repmat({0}, [numArgs 1]);
%# create object
try
obj = feval(ctorMT.Name,args{:});
catch ME
warning(ME.identifier, ME.message)
obj = [];
end
%# store object
objects{i} = obj;
end
As you can see, I found it easier to simply use meta.class
to get metadata about the classes, instead of manually parsing the output of methods('fcn','-full')
as I originally suggested.
However this is not perfect, as there is no way to find out what type of input each constructor expect (only how many). I opted to always pass 0
for each argument..
To test the implementation above, I create these sample classes (one in a self-contained file, the other defined in @-folder with multiple files):
classdef hello
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function val = get.name(obj)
val = obj.name;
end
function obj = set.name(obj,val)
obj.name = val;
end
function say(obj)
fprintf('Hello %s!\n',obj.name);
end
end
end
classdef hello2
properties
name
end
methods
function this = hello2(val)
this.name = val;
end
function val = get.name(obj)
val = obj.name;
end
function obj = set.name(obj,val)
obj.name = val;
end
end
methods
say(obj)
end
end
function say(obj)
fprintf('Hello2 %s!\n', obj.name);
end
Use str2func
to get a function handle to the constructor. You can then call it with whatever arguments are appropriate.
>> m = str2func('containers.Map')
m =
@containers.Map
>> x = m({'foo', 'bar'}, {0, 1})
x =
containers.Map handle
Package: containers
Properties:
Count: 2
KeyType: 'char'
ValueType: 'double'
Methods, Events, Superclasses
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With