Instantiate class from name in MATLAB

陌路散爱 提交于 2020-01-10 14:10:35

问题


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


回答1:


You can use eval to instantiate the class using just the class name.

instance = eval('SimpleString');

However, if you're simply iterating through all the m-files in a folder containing class definitions and grabbing the file names, you'll only be able to invoke the default constructor using this method.




回答2:


Use a package to access class constructors with .()-notation.

A Matlab package is simply a folder/directory with a name that begins with +:

+mypackage/foo.m:

classdef foo
    methods
        function obj = foo(arg1, arg2)
            %foo constructor
        end
    end
end

With class foo defined this way, you can access the constructor of mypackage.foo as

class_name = 'foo';
o = mypackage.(class_name)('arg1_value', 'arg2_value');



回答3:


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



回答4:


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.


EDIT

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):

folder/hello.m

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

folder/@hello2/hello2.m

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

folder/@hello2/say.m

function say(obj)
    fprintf('Hello2 %s!\n', obj.name);
end


来源:https://stackoverflow.com/questions/7102828/instantiate-class-from-name-in-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!