2016-08-02 5 views
1

背景

私は、たとえば.csvファイルとデータベースファイルからデータを抽出して保存するさまざまなタイプのファイルを持っています。それらは通常大容量ファイルであり、私はすでにそれらからデータを抽出するための適切な方法を持っています。入力引数のないオブジェクト配列を作成する

望ましい行動

のは、一例として、クラスtextfileを使用してみましょう。私はtextfileオブジェクトの配列を作成することができたいと思います。各要素は一意のテキストファイルに対応しています。 1つの引数でtextfileに電話することができます。には引数が全くありません。です。私は何も引数を渡さない場合

  1. 、私はファイルを選択するには、ファイル選択画面に移動します、とオブジェクトの配列が作成され、私が選択した各ファイルに1つの要素。

  2. 1つの引数が渡された場合、その引数が何であったかによって、配列を作成したいと思います。ディレクトリパスの場合は、ファイル選択画面を再度開きます。それがファイルパスのセル配列だった場合は、それらのファイルのオブジェクト配列を作成します。

同じ基本動作を持つtextfileのようなクラスを簡単に作成したいと考えています。

試み、これまで

私はすべてのファイルに共通する行動の世話をするためにスーパークラスfileを定義しました。これには、filenameextensionなどのプロパティの割り当てなどが含まれます。私の他のクラスはすべてfileのサブクラスです。

fileのコンストラクタには、2つの入力引数があります。私の考えは、関連するサブクラスのコンストラクタではfileというコンストラクタを呼び出すことでした。最初の入力引数はファイルのタイプです。 txttextfile配列を作成するときに選択した2番目の引数があります。わかりやすくするために、argの唯一のタイプは、どこからファイルを選択するかのディレクトリパスです。何argに応じ

classdef textfile < file 
    methods 
     function textfileObject = textfile(arg) 
      if nargin == 0 
       arg = ''; 
      end 
      [email protected]('txt',arg); 
    end 
end 

fileコンストラクタは、私は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 

オブジェクトアレイはない入力引数とtextfileにinitalizedされた場合、argがコンストラクタの残りの部分で動作''に設定されているためargが、ディレクトリである場合、この作品。

しかし、私はtextfileオブジェクトを作成するときに入力引数を持たないことができますが、コンストラクタの入力引数なしルールでは機能しません。

質問

  1. は、スーパークラスのコンストラクタと

  2. 任意の入力引数を使用していないの呼び出し中にオブジェクトの配列を作成する方法はありますか?

私のファイルタイプごとにクラスを作成するのに役立つ他の解決策があります。

ソリューション

それはあなたが匿名関数を使用してスーパークラスからサブクラスのコンストラクタを呼び出すことができ判明。実際には、入力引数を持たないサブクラスコンストラクタを呼び出してから、入力としてこれらのファイル名で(再帰的に)サブクラスを呼び出す前に、スーパークラスでファイル名を生成することができます。ありがとう@Suever。

サブクラスのコンストラクタは、単純に次のようになります。

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 
+0

fileスーパークラスの中からあなたを正しいサブクラスのコンストラクタを呼び出すと、次のようなものであることを再帰呼び出しを変更することができます入力を提供しないときにファイルを選択するよう求められますか? – Suever

+0

@Suever入力を提供しない場合、デフォルトで作業ディレクトリからファイルを選択するように求められ、オブジェクト配列は選択したファイルに対応する各要素とともに作成されます。 – jenszvs

答えて

1

再帰の配列を生成するためにあなたのクラスのコンストラクタを呼び出すことであろうこれを行う方法:

classdef textfile < file 
    methods 
     function textfileObject = textfile(varargin) 
      [email protected]('txt',varargin{:}); 
     end 
    end 
end 

をとスーパークラスで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 = [email protected]('txt', arg); 
      end 
     end 
    end 
end 

あなたは、基本クラスでこれを実装する場合は、あなたがそう

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

あなたの答えをありがとう!これは 'textfile'クラスの問題を解決します。唯一の悪い点は、私が与えたファイルタイプのすべてのクラスにこのコードを書く必要があるということです。なぜなら、私はそれをすべて処理する 'ファイル'スーパークラスを持つことをお勧めしたいと思ったのです。 'file'スーパークラスのコンストラクタを使ってファイルの選択を処理したい場合、あなたのアプローチを使う方法はありますか? – jenszvs

+0

@ spaggyスーパークラスからこれを行う方法の例を追加しました – Suever

+0

これは、スーパークラスコンストラクタを一度呼び出すだけですが、サブクラスでスーパークラスコンストラクタを呼び出すことは条件ブロック内ではできません。これは、スーパークラスのコンストラクタがサブクラスを呼び出すたびに( 'cellfun'に従って' filelist'の各ファイルに対して1回ずつ)スーパークラスのコンストラクタも呼び出されることを意味します。 – jenszvs

関連する問題