2016-08-02 6 views
1

배경

.csv 및 데이터베이스 파일과 같이 데이터를 추출하고 저장하는 여러 유형의 파일이 있습니다. 대개 대용량 파일이므로 데이터를 추출하는 적절한 방법이 이미 있습니다.입력 인수가없는 객체 배열 구성

원하는 동작

는의 한 예로 클래스 textfile을 사용하자. 각 요소가 고유 한 텍스트 파일에 해당하는 textfile 개체의 배열을 만들 수 있기를 바랍니다. 하나의 인수로 textfile으로 전화를 걸거나 에 인수가 전혀 없으면으로 전화를 걸고 싶습니다. 내가 어떤 인수를 전달하지 않으면

  1. 가, 내가 파일을 선택하는 파일 선택 화면으로 이동합니다, 그리고 객체 배열이 생성됩니다, 각 파일에 대한 하나 개의 요소는 내가 선택했습니다.

  2. 하나의 인수가 전달되면 해당 인수가 무엇인지에 따라 배열을 생성하고 싶습니다. 디렉토리 경로 인 경우 파일 선택 화면을 다시 엽니 다. 파일 경로의 셀 배열이면 해당 파일의 객체 배열을 만듭니다.

나는 쉽게 같은 기본 동작을 textfile처럼 이상의 클래스를 만들 수 있도록하고 싶습니다

.

시도는 지금까지

나는 모든 파일에 행동주의 일반을하는 슈퍼 클래스 file을 정의했다. 여기에는 filenameextension과 같은 속성 할당과 같은 항목이 포함됩니다. 내 다른 클래스는 모두 file의 하위 클래스입니다.

file의 생성자에는 두 개의 입력 인수가 있습니다. 내 생각은 관련 하위 클래스 생성자에서 file 생성자를 호출하는 것이 었습니다. 첫 번째 입력 인수는 파일 형식입니다 (예 : txt이고, 두 번째는 textfile 배열을 만들 때 내가 선택한 인수입니다. 단순화를 위해, arg의 유일한 유형은 파일을 선택할 위치의 디렉토리 경로입니다. 어떤 arg에 따라

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

file 생성자, I는 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. 모든 입력 인수를 사용하지를 호출하는 동안 객체 배열을 만들 수있는 방법이 있나요?

각 파일 유형에 대한 클래스를 만드는 데 도움이되는 다른 솔루션에 대해 열려 있습니다.

솔루션

그것은 당신이 익명 함수를 사용하여 수퍼 클래스에서 하위 클래스의 생성자를 호출 할 수 있습니다 밝혀졌습니다. 결과적으로 입력 인자가없는 subclass 생성자를 호출 한 다음 입력으로 이들 파일 이름을 사용하여 (재귀 적으로) 서브 클래스를 다시 호출하기 전에 수퍼 클래스에서 파일 이름을 생성 할 수 있습니다. @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

그래서 당신에게 내에서 올바른 서브 클래스의 생성자를 호출 할 다음과 같은 것으로 재귀 호출을 바꿀 수 입력을 제공하지 않을 때 파일을 선택하라는 메시지가 나타 납니까? – 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 

, 당신은 file 슈퍼 클래스

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

답변 해 주셔서 감사합니다! 그것은'textfile' 클래스의 문제를 해결합니다. 유일한 나쁜 점은 주어진 파일 유형에 대한 모든 클래스에이 코드 조각을 써야한다는 것을 의미하는 것입니다. 그렇기 때문에 모든 파일 클래스를 처리 할 수있는'파일 '수퍼 클래스를 갖는 것이 좋습니다. . 파일 선택을 처리하기 위해'file' 수퍼 클래스 생성자를 사용하고자 할 때 접근법을 사용할 수 있습니까? – jenszvs

+0

@spaggy 슈퍼 클래스에서이 작업을 수행하는 방법에 대한 예제를 추가했습니다 – Suever

+0

이 문제는 한 번만 수퍼 클래스 생성자를 호출하려고하지만 하위 클래스의 수퍼 클래스 생성자를 호출하는 것이 조건부 블록 내에서 수행 될 수 없다는 것입니다. 이것은 수퍼 클래스 생성자가 서브 클래스를 호출 할 때마다 ('cellfun'에 따라'filelist'에있는 각 파일에 대해 한번씩) 수퍼 클래스 생성자가 호출 될 것이라는 것을 의미합니다. – jenszvs