Фон
У меня есть разные типы файлов, из которых я извлекаю и храню данные, например .csv и файлы базы данных. Обычно это большие файлы, и у меня уже есть соответствующие методы для извлечения из них данных.
Желаемое поведение
Давайте использовать класс textfile
в качестве примера. Я хотел бы иметь возможность создать массив объектов textfile
, где каждый элемент соответствует уникальному текстовому файлу. Я хотел бы иметь возможность вызывать textfile
с одним аргументом или вообще без аргументов.
Если я не передам никаких аргументов, я попаду на экран выбора файлов, чтобы выбрать файлы, и будет создан массив объектов, по одному элементу для каждого выбранного файла.
Если передается один аргумент, я бы хотел, чтобы массив создавался в зависимости от того, что это был за аргумент. Если это был путь к каталогу, снова откройте экран выбора файла. Если это был массив ячеек с путями к файлам, создайте массив объектов из этих файлов.
Я хотел бы иметь возможность легко создавать больше классов, таких как textfile
, которые имеют такое же базовое поведение.
Попытки до сих пор
Я определил суперкласс file
, чтобы позаботиться об общем для всех файлов поведении. Это включает в себя такие вещи, как назначение таких свойств, как filename
и extension
. Все остальные мои классы являются подклассами 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
, генерирует массив объектов в соответствии с с использованием требования конструктора без входных аргументов.
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 для конструкторов.
Вопрос
Есть ли способ создавать массивы объектов, в то время как
вызов конструктора суперкласса и
не используя никаких входных аргументов?
Я открыт для других решений, которые могут помочь с моей проблемой создания классов для каждого из моих типов файлов.
Решение
Оказывается, конструктор подкласса можно вызвать из суперкласса с помощью анонимной функции. По сути, вы можете вызвать конструктор подкласса без входных аргументов, а затем сгенерировать имена файлов в суперклассе перед повторным вызовом подкласса (рекурсивно) с этими именами файлов в качестве входных данных. Спасибо @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