Создать экземпляр класса по имени в MATLAB - PullRequest
12 голосов
/ 18 августа 2011

Я пытаюсь перечислить классы, которые я создал в какой-то папке в моей папке Matlab - используя только их имя (имя класса)

Например, у меня есть класс с именем SimpleString - и я собираюсь создать экземпляр объекта из этого класса, если я знаю только то, что его имя - SimpleString *

Так что в реальном времени я хотел бы узнать, какие классы находятся в папке (готово), а затем иметь возможность создать экземпляр любого из этих классов (мой вопрос) Спасибо

Ответы [ 4 ]

12 голосов
/ 22 ноября 2013

Используйте пакет для доступа к конструкторам классов с помощью .() -notation.

A Пакет Matlab - это просто папка / каталог, имя которого начинается с+:

+ mypackage / foo.m:

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

Определив таким образом класс foo, вы можете получить доступ к конструктору mypackage.foo как

class_name = 'foo';
o = mypackage.(class_name)('arg1_value', 'arg2_value');
10 голосов
/ 18 августа 2011

Используйте str2func, чтобы получить дескриптор функции для конструктора.Затем вы можете вызвать его с любыми подходящими аргументами.

>> 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
6 голосов
/ 18 августа 2011

Вы можете использовать функцию WHAT для обнаружения классов (а также функций, пакетов и т. Д.) В определенной папке, а затем вызвать METHODS , чтобы найти подпись конструктор класса (здесь требуется некоторый синтаксический анализ), наконец, используя FEVAL (передавая аргументы, если таковые имеются) для создания объекта из этого класса.

Вы также можете использовать meta.class для получения всех видов метаинформации о ваших классах.


EDIT

Вот код, иллюстрирующий то, что я имел в виду:

%# 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

Как видите, я обнаружил, что проще использовать meta.class для получения метаданных о классах, вместо того, чтобы вручную анализировать вывод methods('fcn','-full'), как я изначально предлагал.

Однако это не идеально, так как нет способа узнать, какой тип ввода ожидает каждый конструктор (только сколько). Я решил всегда передавать 0 для каждого аргумента ..

Чтобы проверить приведенную выше реализацию, я создаю эти примеры классов (один в отдельном файле, другой - в @-папке с несколькими файлами):

папка / 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
4 голосов
/ 18 августа 2011

Вы можете использовать eval для создания экземпляра класса, используя только имя класса.

instance = eval('SimpleString');

Однако, если вы просто перебираете все m-файлы впапка, содержащая определения классов и захват имен файлов, вы сможете вызывать конструктор по умолчанию только с помощью этого метода.

...