构造没有输入参数的对象数组
Construct object array with no input arguments
背景
我从不同类型的文件中提取和存储数据,例如 .csv 和数据库文件。它们通常是大文件,我已经有适当的方法从中提取数据。
期望的行为
我们以class textfile
为例。我希望能够创建一个 textfile
对象数组,其中每个元素对应一个唯一的文本文件。我希望能够用一个参数调用 textfile
,或者 根本没有参数。
如果我不传递任何参数,我将被带到文件 select 屏幕到 select 文件,并且将创建一个对象数组,一个元素用于每个文件我 selected.
如果传递了一个参数,我希望根据该参数创建数组。如果是目录路径,请再次打开文件 select 屏幕。如果它是文件路径的元胞数组,则创建这些文件的对象数组。
我希望能够轻松创建更多 class 具有相同基本行为的 textfile
。
到目前为止的尝试
我定义了一个 superclass file
来处理所有文件共有的行为。这包括分配 filename
和 extension
等属性。我的其他 class 都是 file
.
的子class
在 file
的构造函数中,我有两个输入参数。我的想法是,在相关的 subclass 构造函数中,我会调用 file
构造函数。第一个输入参数是文件类型,例如txt
,而第二个是我在创建 textfile
数组时选择的参数。为简单起见,假设我希望能够处理的唯一类型 arg
是从中选择文件的目录路径。
classdef textfile < file
methods
function textfileObject = textfile(arg)
if nargin == 0
arg = '';
end
textfileObject@file('txt',arg);
end
end
file
构造函数,根据我创建textfile
对象时arg
是什么,按照using the No Input Argument Constructor Requirement.[=36=生成对象数组]
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
对象时能够没有任何输入参数,但这不适用于构造函数的无输入参数规则。
问题
有没有办法在
时创建对象数组
调用超级class构造函数和
没有使用任何输入参数?
我对其他解决方案持开放态度,这些解决方案可以帮助我解决为每种文件类型创建 classes 的问题。
解决方案
事实证明,您可以使用匿名函数从 superclass 调用 subclass 构造函数。实际上,您可以调用没有输入参数的 subclass 构造函数,然后在使用这些文件名作为输入再次(递归)调用 subclass 之前在 superclass 中生成文件名.谢谢@Suever。
subclass 构造函数将只是:
classdef textfile < file
methods
function textfileObject = textfile(varargin)
textfileObject@file('txt',varargin{:});
end
end
end
而在超class:
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
执行此操作的方法是递归调用 class 的构造函数以生成 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
如果你想在基础 class 中实现它,你可以将递归调用更改为如下所示,它会从 [=13] 中调用正确的 subclass 构造函数=]超级class
constructor = @(varargin)feval(class(self), varargin{:});
output = cellfun(constructor, filelist, 'uniformoutput', 0);
背景
我从不同类型的文件中提取和存储数据,例如 .csv 和数据库文件。它们通常是大文件,我已经有适当的方法从中提取数据。
期望的行为
我们以class textfile
为例。我希望能够创建一个 textfile
对象数组,其中每个元素对应一个唯一的文本文件。我希望能够用一个参数调用 textfile
,或者 根本没有参数。
如果我不传递任何参数,我将被带到文件 select 屏幕到 select 文件,并且将创建一个对象数组,一个元素用于每个文件我 selected.
如果传递了一个参数,我希望根据该参数创建数组。如果是目录路径,请再次打开文件 select 屏幕。如果它是文件路径的元胞数组,则创建这些文件的对象数组。
我希望能够轻松创建更多 class 具有相同基本行为的 textfile
。
到目前为止的尝试
我定义了一个 superclass file
来处理所有文件共有的行为。这包括分配 filename
和 extension
等属性。我的其他 class 都是 file
.
在 file
的构造函数中,我有两个输入参数。我的想法是,在相关的 subclass 构造函数中,我会调用 file
构造函数。第一个输入参数是文件类型,例如txt
,而第二个是我在创建 textfile
数组时选择的参数。为简单起见,假设我希望能够处理的唯一类型 arg
是从中选择文件的目录路径。
classdef textfile < file
methods
function textfileObject = textfile(arg)
if nargin == 0
arg = '';
end
textfileObject@file('txt',arg);
end
end
file
构造函数,根据我创建textfile
对象时arg
是什么,按照using the No Input Argument Constructor Requirement.[=36=生成对象数组]
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
对象时能够没有任何输入参数,但这不适用于构造函数的无输入参数规则。
问题
有没有办法在
时创建对象数组调用超级class构造函数和
没有使用任何输入参数?
我对其他解决方案持开放态度,这些解决方案可以帮助我解决为每种文件类型创建 classes 的问题。
解决方案
事实证明,您可以使用匿名函数从 superclass 调用 subclass 构造函数。实际上,您可以调用没有输入参数的 subclass 构造函数,然后在使用这些文件名作为输入再次(递归)调用 subclass 之前在 superclass 中生成文件名.谢谢@Suever。
subclass 构造函数将只是:
classdef textfile < file
methods
function textfileObject = textfile(varargin)
textfileObject@file('txt',varargin{:});
end
end
end
而在超class:
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
执行此操作的方法是递归调用 class 的构造函数以生成 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
如果你想在基础 class 中实现它,你可以将递归调用更改为如下所示,它会从 [=13] 中调用正确的 subclass 构造函数=]超级class
constructor = @(varargin)feval(class(self), varargin{:});
output = cellfun(constructor, filelist, 'uniformoutput', 0);