构造没有输入参数的对象数组

时间:2016-08-02 14:52:41

标签: arrays matlab object constructor superclass

背景

我有不同类型的文件,我从中提取并存储数据,例如.csv和数据库文件。它们通常是大文件,我已经有适当的方法从中提取数据。

期望的行为

让我们以班级textfile为例。我希望能够创建一个textfile个对象数组,其中每个元素对应一个唯一的文本文件。我希望能够用一个参数调用textfile,或者根本没有参数

  1. 如果我不传递任何参数,我将被带到文件选择屏幕以选择文件,并将创建一个对象数组,我选择的每个文件都有一个元素。

    < / LI>
  2. 如果传递了一个参数,我希望根据参数是什么来创建数组。如果是目录路径,请再次打开文件选择屏幕。如果它是文件路径的单元格数组,请创建这些文件的对象数组。

  3. 我希望能够轻松创建更多具有相同基本行为的textfile类。

    到目前为止的尝试

    我已经定义了一个超类file来处理所有文件的共同行为。这包括分配filenameextension等属性。我的其他类都是file的子类。

    file的构造函数中,我有两个输入参数。我的想法是,在相关的子类构造函数中,我调用file构造函数。第一个输入参数是文件类型,例如txt,而第二个是我在创建textfile数组时选择的参数。为简单起见,我们说我希望能够处理的唯一arg类型是从哪里选择文件的目录路径。

    classdef textfile < file
        methods
            function textfileObject = textfile(arg)
                if nargin == 0
                    arg = '';
                end
                textfileObject@file('txt',arg);
        end
    end
    

    file构造函数取决于创建arg对象时textfile的内容,根据using the No Input Argument Constructor Requirement生成对象数组。

    classdef file < handle
        properties
            Path
        end
        methods
            function FileObject = file(FileType,arg)
                if nargin == 2
                    FileList = file.SelectFiles(FileType,arg);
                    FileObject(numel(FileList),1) = file;
                    for filecount = 1:numel(FileObject)
                        FileObject(filecount,1).Path = FileList{filecount};
                    end
                end
            end
        end
        methods(Static)
            function FileList = SelectFiles(DirectoryPath)
                 % Some selection dialogs. Returns a cell array of filepaths
            end
        end
    end
    

    arg是一个目录时,这是有效的,因为当textfile中没有输入参数的对象数组被初始化时,arg被设置为'',它与其余的建设者。

    但是,我希望在创建textfile对象时不能有任何输入参数,但这并不适用于构造函数的No Input Argument规则。

    问题

    有没有办法在

    时创建对象数组
    1. 调用超类构造函数和

    2. 不使用任何输入参数?

    3. 我可以使用其他解决方案来解决我为每种文件类型创建类的问题。

      解决方案

      事实证明,您可以使用匿名函数从超类中调用子类构造函数。实际上,您可以在没有输入参数的情况下调用子类构造函数,然后在使用这些文件名作为输入再次(递归地)调用子类之前,在超类中生成文件名。谢谢@Suever。

      子类构造函数将只是:

      classdef textfile < file
          methods
              function textfileObject = textfile(varargin)
                  textfileObject@file('txt',varargin{:});
              end
          end
      end
      

      在超类中:

      classdef file < handle
          properties
              Path
          end
          methods
              function FileObject = file(FileType,varargin)
      
                  % Subclass constructor handle
                  Constructor = @(FilePath)feval(class(FileObject),FilePath);
      
                  % No subclass arguments
                  if nargin == 1
                      FileList = file.SelectFiles(FileType,'');
                      for a = 1:numel(FileList)
                          FileObject(a,1) = Constructor(FileList{a});
                      end
      
                  % One subclass argument
                  elseif nargin == 2
                      arg = varargin{1};
                      if ischar(arg)
                          FileStruct = dir(arg);
                          if numel(FileStruct) == 1
                              FileObject.Path = arg;
                          end
                      end
      
                  % Too many subclass arguments
                  else
                      error('Subclasses of file only take one or no input arguments');
                  end
              end
          end
      end
      

1 个答案:

答案 0 :(得分:1)

执行此操作的方法是递归调用类的构造函数以生成textfile个对象的数组。

classdef textfile < file

    methods
        function self = textfile(arg)
            if ~exist('arg', 'var')
                % Get list of files somehow
                [fnames, pname] = uigetfile('MultiSelect', 'on');
                filelist = fullfile(pname, fnames);

                % Call the constructor again for each file
                output = cellfun(@textfile, filelist, 'uniformoutput', 0);

                % Flatten the cell array of objects into an array of the right shape
                self = reshape([output{:}], size(filelist));
            else
                % Do default construction here
                self = self@file('txt', arg);
            end
        end
    end
end

如果要在基类中实现它,可以将递归调用更改为类似以下内容,从file超类中调用正确的子类构造函数

constructor = @(varargin)feval(class(self), varargin{:});
output = cellfun(constructor, filelist, 'uniformoutput', 0);