Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 在MATLAB中从名称实例化类_Oop_Class_Matlab_Dynamic_Instantiation - Fatal编程技术网

Oop 在MATLAB中从名称实例化类

Oop 在MATLAB中从名称实例化类,oop,class,matlab,dynamic,instantiation,Oop,Class,Matlab,Dynamic,Instantiation,我试图列出我在Matlab文件夹的某个文件夹中创建的类-仅使用它们的名称(类名) 例如,我有一个名为“SimpleString”的类,我的目标是从该类实例化一个对象,如果我只知道它的名称是“SimpleString” 因此,在实时中,我想找出文件夹中有哪些类(完成),然后能够实例化这些类中的任何一个(我的问题) 谢谢您可以使用仅使用类名来实例化类 instance = eval('SimpleString'); 但是,如果您只是遍历包含类定义的文件夹中的所有m文件并获取文件名,则只能使用此方法

我试图列出我在Matlab文件夹的某个文件夹中创建的类-仅使用它们的名称(类名)

例如,我有一个名为“SimpleString”的类,我的目标是从该类实例化一个对象,如果我只知道它的名称是“SimpleString”

因此,在实时中,我想找出文件夹中有哪些类(完成),然后能够实例化这些类中的任何一个(我的问题) 谢谢

您可以使用仅使用类名来实例化类

instance = eval('SimpleString');
但是,如果您只是遍历包含类定义的文件夹中的所有m文件并获取文件名,则只能使用此方法调用默认构造函数。

您可以使用该函数发现特定文件夹中的类(以及函数、包等),然后调用以查找类的构造函数的签名(此处需要一些解析),最后使用(传递参数,如果有)从此类创建对象

您还可以使用获取有关类的各种元信息


编辑 下面是一些代码来说明我的想法:

%# 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
来获取有关类的元数据更容易,而不是像我最初建议的那样手动解析
方法('fcn','-full')
的输出

然而,这并不完美,因为没有办法找出每个构造函数期望的输入类型(只有多少)。我选择始终为每个参数传递
0

为了测试上述实现,我创建了以下示例类(一个在自包含文件中,另一个在@文件夹中定义,包含多个文件):

folder/hello.m 文件夹/@hello2/hello2.m folder/@hello2/say.m
使用
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

使用访问带有
()
-符号的类构造函数

A只是一个名称以
+
开头的文件夹/目录:

+mypackage/foo.m: 通过这样定义类
foo
,您可以按如下方式访问
mypackage.foo的构造函数

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

这对我的目标很有效——我已经涵盖了所有的“发现”和元数据。我只需要实例化一下。谢谢
eval
可以用来执行任意的MATALB代码,有人可以很容易地插入
eval('delete('*.m'))
并删除您的所有代码文件
feval
使用起来更安全虽然人们可以做
feval('delete','*.m')
,但这稍微难一点。@Sam对,因为稍微难一点就足以防止人们做恶意的事情:)Amro的答案比我的好,不确定OP为什么没有选择那一个。很好,简洁。如果有人有很好的理由不在简单的情况下使用它,我很想听听。这似乎比使用
eval
要好得多。
function say(obj)
    fprintf('Hello2 %s!\n', obj.name);
end
>> 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
classdef foo
    methods
        function obj = foo(arg1, arg2)
            %foo constructor
        end
    end
end
class_name = 'foo';
o = mypackage.(class_name)('arg1_value', 'arg2_value');