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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.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_Matlab_Inheritance_Constructor - Fatal编程技术网

Oop 在MATLAB中如何在基类构造函数中调用合适的子类构造函数

Oop 在MATLAB中如何在基类构造函数中调用合适的子类构造函数,oop,matlab,inheritance,constructor,Oop,Matlab,Inheritance,Constructor,我试图在Matlab中使用单继承,并编写一个基类构造函数,允许创建对象数组,包括空数组,并由子类继承。如果不使用一些令人难以置信的笨拙代码,我就无法解决如何做到这一点。一定有更好的办法 在这个玩具示例中,我的基类称为MyBaseClass,子类称为MySubClass。每个都可以用一个数值参数构造,也可以不构造参数(在这种情况下,假定为NaN)。在toy示例中,我的子类很简单,并且没有以任何方式扩展MyBaseClass的行为,但显然在实践中它会做更多的事情 我希望能够按如下方式调用每个的构造函

我试图在Matlab中使用单继承,并编写一个基类构造函数,允许创建对象数组,包括空数组,并由子类继承。如果不使用一些令人难以置信的笨拙代码,我就无法解决如何做到这一点。一定有更好的办法

在这个玩具示例中,我的基类称为MyBaseClass,子类称为MySubClass。每个都可以用一个数值参数构造,也可以不构造参数(在这种情况下,假定为NaN)。在toy示例中,我的子类很简单,并且没有以任何方式扩展MyBaseClass的行为,但显然在实践中它会做更多的事情

我希望能够按如下方式调用每个的构造函数:

obj = MyBaseClass;     % default constructor of 'NaN-like' object
obj = MyBaseClass([]); % create an empty 0x0 array of type MyBaseClass
obj = MyBaseClass(1);  % create a 1x1 array of MyBaseClass with value 1
obj = MyBaseClass([1 2; 3 4]) % create a 2x2 array of MyBaseClass with values 1, 2, 3, 4.
对MySubClass也有同样的四个调用

我找到的解决方案需要调用
eval(class(obj))
,以便在基类构造函数中恢复子类名称并以字符串形式构造要调用的代码。这看起来既笨重又糟糕。(这对我来说有点奇怪,这是可能的,但事实确实如此。)我想我可以在
MyBaseClass
MySubClass
构造函数之间复制更多的逻辑,但这似乎也很笨拙和糟糕,并且忽略了继承的意义。有更好的办法吗

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MyBaseClass.m

classdef MyBaseClass

    properties
        data = NaN        
    end

    methods

        % constructor
        function obj = MyBaseClass(varargin)
            if nargin == 0
                % Handle the no-argument case
                return
            end

            arg = varargin{1};

            % assume arg is a numeric array
            if isempty(arg)
                % Handle the case ClassName([])

                % Can't write this, because of subclasses:
                % obj = MyBaseClass.empty(size(arg));

                obj = eval([class(obj) '.empty(size(arg))']);
                return
            end

            % arg is an array
            % Make obj an array of the correct size by allocating the nth
            % element. Need to recurse for the no-argument case of the
            % relevant class constructor, which might not be this one.

            % Can't write this, because of subclasses
            % obj(numel(arg)) = MyBaseClass;

            obj(numel(arg)) = eval(class(obj));

            % Rest of the constructor - obviously in this toy example,
            % could be simplified.
            wh = ~isnan(arg);
            for i = find(wh(:))'
                obj(i).data = arg(i);
            end
            % And reshape to the size of the original
            obj = reshape(obj, size(arg));
        end

    end

end

% end of MyBaseClass.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MySubClass.m

classdef MySubClass < MyBaseClass

    methods
        function obj = MySubClass(varargin)
            obj = obj@MyBaseClass(varargin{:});
        end
    end 
end

% end of MySubClass.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%MyBaseClass.m
classdef MyBaseClass
性质
数据=NaN
结束
方法
%建造师
函数obj=MyBaseClass(varargin)
如果nargin==0
%处理无争论的情况
返回
结束
arg=varargin{1};
%假设arg是一个数字数组
如果为空(arg)
%处理案例类名称([])
%无法写入此内容,因为子类:
%obj=MyBaseClass.empty(大小(arg));
obj=eval([class(obj)”.empty(size(arg))”);
返回
结束
%arg是一个数组
%通过分配第n个数组,使obj成为一个大小正确的数组
%元素。对于的无参数情况,需要递归
%相关的类构造函数,可能不是这个。
%由于子类的原因,无法编写此代码
%obj(numel(arg))=MyBaseClass;
obj(numel(arg))=评估(类(obj));
%构造器的其余部分-显然在这个玩具示例中,
%可以简化。
wh=~isnan(arg);
for i=find(wh(:)'
obj(i)。数据=arg(i);
结束
%并重塑为原始尺寸
obj=重塑(obj,尺寸(arg));
结束
结束
结束
%MyBaseClass.m的结尾
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%MySubClass.m
classdef MySubClass
您的解决方案是功能性的,包含一些松散的MATLAB类型以实现您想要的。然而,要获得干净和结构化的OOP,可能需要失去一些您想要的功能。同时,避免代码重复的最佳选择是模板化/通用容器类,但目前MATLAB不支持这些类

您的代码反映了MATLAB文档,并依赖于MATLAB是一种松散类型的语言,它使您能够毫无问题地将对象转换为对象数组。利用MATLAB强大而灵活的特性确实会带来一些组织问题,可能会破坏您在干净、面向对象代码方面的努力。 出现问题的原因是MyBaseClass构造函数不是MyBaseClass的真正构造函数

维基百科:

在面向对象编程中,构造函数(有时简称为ctor)在类中,是在创建对象时调用的一种特殊类型的子例程。它准备使用新对象,通常接受构造函数在首次创建对象时用来设置所需的任何成员变量的参数。之所以称为构造函数,是因为它构造类的数据成员的值。”

请注意,MyBaseClass构造函数没有为对象成员构造值。相反,它是一个函数,将对象设置为MyBaseClass类型的对象数组,并尝试将其数据成员设置为某个值。您可以在此处看到obj在设置为阵列时被销毁的位置:

obj(numel(arg)) = eval(class(obj));
当您从MyBaseClass派生MySubClass时,这种行为尤其没有帮助,因为MyBaseClass不应该将新对象分配给变量obj——MySubClass已经在obj中创建了新对象,并且只是要求MyBaseClass在obj中构造MyBaseClass知道细节的现有对象部分因为

注意,当您为MyBaseClass和MySubClass输入构造函数时,变量obj已经填充了一个非常好的类实例,这可能会让您更加清楚。良好的OOP实践会让您保留这个原始实例,在基类构造函数中使用它,并且只在构造函数中填充它的成员——而不是用新的内容完全覆盖对象。 我的结论是不要将obj指定为MyBaseClass内部的数组。相反,我建议创建一个类MyBaseClassArray来创建MyBaseClass对象的数组

不幸的是,您还需要创建一个重复的类MySubClassArray来创建一个MySubClass对象数组。像C++和java这样的语言可以分别解决模板复制和泛型的代码复制问题,但是Matlab目前不支持任何形式的模板(http://www.mathworks.com/he