Main Content

배열 생성 함수에 대한 클래스 지원

클래스에 대해 배열 생성 함수 확장하기

oneszeros처럼 특정 크기와 유형의 배열을 생성하는 여러 MATLAB® 함수가 있습니다. 이러한 함수 대부분은 클래스와 함께 사용할 수 있도록 오버로드할 수 있습니다. 이 항목에는 그 절차가 설명되어 있습니다. 기존 함수를 오버로드하지 않고 객체 배열을 생성하는 옵션은 객체 배열을 만들고 초기화하기 항목을 참조하십시오.

참고

createArray (R2024a 이후)는 여러 클래스에 대해 오버로드 없이 배열을 생성할 수 있도록 지원합니다. 자세한 내용은 createArray 항목을 참조하십시오. createArray를 오버로드하는 것이 유용할 수 있는 경우에 대한 자세한 내용은 구현할 createArray 메서드 항목을 참조하십시오.

배열 생성 함수에 클래스가 지원되면 내장 데이터형 및 사용자 정의 데이터형과 공유 가능한 코드를 개발할 수 있습니다. 예를 들어, 다음 코드에서 변수 x의 클래스는 초기 개발 중에는 내장 유형이었다가 zeros를 투명하게 오버로드하는 사용자 정의 클래스로 대체될 수 있습니다.

cls = class(x);
zArray = zeros(m,n,cls);

배열 생성 함수는 다음의 두 가지 방법으로 특정 유형의 배열을 생성합니다.

  • 클래스 이름 구문 — 클래스 이름을 지정하여 이를 통해 배열 요소의 유형을 결정합니다.

  • prototype 객체 구문 — prototype 객체를 제공하여 함수가 이를 사용해 배열 요소의 유형과 기타 특성을 결정하도록 합니다.

예를 들면 다음과 같습니다.

zArray = zeros(2,3,'uint8');
p = uint8([1 3 5; 2 4 6]);
zArray = zeros(2,3,'like',p);

이들 함수에 대한 지원을 MyClass라는 클래스에 추가하면 유사한 구문을 이 클래스와 함께 사용할 수 있습니다.

zArray = zeros(2,3,'MyClass');

또는 클래스의 객체를 전달할 수 있습니다.

p = MyClass(...);
zArray = zeros(size(p),'like',p);

MATLAB은 이러한 인수를 사용하여 클래스의 적절한 메서드에 디스패치합니다.

오버로드를 지원하는 배열 생성 함수

다음 함수는 이 유형의 오버로드를 지원합니다.

오버로드를 지원하는 스칼라 함수

다음 함수들도 유사한 오버로드를 지원하며, 출력값이 항상 스칼라(또는 1×1 희소 행렬)라는 점만 다릅니다.

이들 함수는 특정 유형의 스칼라를 생성할 때 크기를 지정하지 않아도 됩니다. 예를 들면 다음과 같습니다.

d = eps('single');
p = single([1 3 5; 2 4 6]);
d = eps('like',p);

이들 함수에 대한 지원을 사용자 정의 클래스에 추가하면 유사한 구문을 이 클래스와도 함께 사용할 수 있습니다.

각 구문을 사용하는 경우

클래스는 클래스 이름 구문과 prototype 객체 구문을 모두 지원할 수 있습니다. 디폴트 객체로 구성된 배열을 생성하려면 클래스 이름 구문을 사용하십시오. 유형, 실수/복소수 여부 및 그 밖의 속성이 기존 객체와 동일한 객체로 구성된 배열을 생성하려면 prototype 구문을 사용하십시오.

배열 생성 함수에 대한 지원 구현

두 개의 별도의 메서드를 사용하여 배열 생성 함수를 지원합니다. 한 메서드는 클래스 이름 구문을 구현하고 다른 메서드는 prototype 객체 구문을 구현합니다.

예를 들어, zeros 함수를 지원하려면 다음을 수행하십시오.

  • 다음의 클래스 이름 구문을

    zeros(...,'ClassName')

    Static 메서드로 구현합니다.

    methods (Static)
       function z = zeros(varargin)
          ...
       end
    end
  • 다음의 prototype 객체 구문을

    zeros(...,'like',obj)

    Hidden 메서드로 구현하고 이름에 char형 벡터 'Like'를 추가합니다.

    methods (Hidden)
       function z = zerosLike(obj,varargin)
          ...
       end
    end

MATLAB이 함수 호출을 해석하는 방법

구문의 해석에 따라 배열 생성 함수의 특수한 지원이 가능합니다.

  • 다음 형식으로 zeros 함수를 호출하면

    zeros(...,'ClassName')
    

    다음 구문을 사용하여 클래스 정적 메서드를 호출합니다.

    ClassName.zeros(varargin{1:end-1})
  • 다음 형식으로 zeros 함수를 호출하면

    zeros(...,'like',obj)

    다음 구문을 사용하여 클래스 메서드를 호출합니다.

    zerosLike(obj,varargin{1:end-2})

프로토타입 메서드가 존재하지 않는 경우 클래스 이름 메서드가 호출됨

클래스가 클래스 이름 구문을 구현하지만 특정 함수에 대한 prototype 객체 구문을 구현하지 않는 경우에도 두 구문을 모두 호출할 수 있습니다. 예를 들어, 정적 zeros 메서드만 구현한 경우 다음을 호출할 수 있습니다.

zeros(...,'like',MyClass(...))

prototype 객체 구문을 호출하면 MATLAB은 먼저 zerosLike라는 메서드를 찾습니다. MATLAB이 이 메서드를 찾을 수 없으면 zeros 정적 메서드를 호출합니다.

이 기능은 배열을 생성하는 데 클래스 이름만 필요한 경우에 유용합니다. 배열 생성 함수 구문을 완전히 지원하기 위해 두 가지 메서드를 모두 구현할 필요는 없습니다. 클래스 이름 구문만 구현한 경우 prototype 객체 구문에 대한 호출은 클래스 이름 구문에 대한 호출과 동일합니다.

모든 함수 입력값 지원하기

배열 생성 함수에 대한 입력 인수에는 함수가 반환하는 배열의 차원과 그 밖의 다른 인수가 포함될 수 있습니다. 일반적으로 메서드가 지원해야 하는 경우는 다음 세 가지입니다.

  • 차원 입력 인수가 없는 경우, 스칼라를 반환합니다. 예를 들면 다음과 같습니다.

    z = zeros('MyClass');
  • 하나 이상의 차원이 0보다 작거나 같은 경우, 빈 배열이 생성됩니다. 예를 들면 다음과 같습니다.

    z = zeros(2,0,'MyClass');
  • 유효한 수의 배열 차원인 경우, 배열 크기가 지정됩니다. 예를 들면 다음과 같습니다.

    z = zeros(2,3,5,'MyClass');

배열 생성 함수는 클래스 메서드를 호출할 때 클래스 이름이나 리터럴 'like'를 제외한 입력 인수와 객체 변수를 메서드에 전달합니다. 다음 시그니처를 사용하여 메서드를 구현할 수 있습니다.

  • “class name” 메서드의 경우 zeros(varargin)

  • “like prototype object” 메서드의 경우 zeros(obj,varargin)

예제 클래스

Color 클래스는 RGB, HSV 등과 같은 특정 컬러스페이스의 색을 나타냅니다. 클래스 이름 메서드 구현 항목 및 prototype 객체 메서드 구현 항목의 설명에서는 이 클래스를 오버로드된 메서드 구현의 기반으로 사용합니다.

classdef Color
   properties
      ColorValues = [0,0,0]
      ColorSpace = 'RGB'
   end
   methods
      function obj = Color(cSpace,values)
         if nargin > 0
            obj.ColorSpace = cSpace;
            obj.ColorValues = values;
         end
      end
   end
end

클래스 이름 메서드 구현

zeros 함수는 마지막 ClassName char형 벡터를 제거하고 이를 사용하여 Color 클래스의 정적 메서드 호출을 형성합니다. 정적 메서드에 전달되는 인수는 배열 차원 인수입니다.

다음은 Color 클래스에 대한 zeros 메서드를 구현한 것입니다. 이 구현은 다음과 같습니다.

  • zeros 메서드를 Static으로 정의합니다(필수).

  • zeros에 대한 호출에서 차원 인수가 없으면 스칼라 Color 객체를 반환합니다.

  • zeros에 대한 호출에서 차원 인수가 0이면 빈 배열을 반환합니다.

  • 디폴트 Color 객체로 구성된 배열을 반환합니다. repmat를 사용하여 zeros에 대한 호출에 의해 지정된 차원의 배열을 만듭니다.

classdef Color
   ...
   methods (Static)
      function z = zeros(varargin)
         if (nargin == 0)
         % For zeros('Color')
            z = Color;
         elseif any([varargin{:}] <= 0)
         % For zeros with any dimension <= 0   
            z = Color.empty(varargin{:});
         else
         % For zeros(m,n,...,'Color')
         % Use property default values
            z = repmat(Color,varargin{:});
         end
      end
   end
end

이 응용 사례에서는 디폴트 값이 적합하기 때문에 zeros 메서드는 ColorValues 속성에 디폴트 값을 사용합니다. 예를 들어, ones 메서드의 구현에서 ColorValues 속성을 [1,1,1]로 설정할 수 있습니다.

다음과 같은 목표를 달성하기 위해 randi 함수를 오버로드한다고 가정하겠습니다.

  • ColorValue 속성을 1에서 지정된 최댓값 사이(예: 1~255)의 1×3 배열로 정의합니다.

  • 스칼라, 비어 있는 경우, 다차원의 배열 크기를 수용합니다.

  • 각각 임의의 ColorValues를 가진, 지정된 차원의 Color 객체로 구성된 배열을 반환합니다.

classdef Color
   ...
   methods (Static)
      function r = randi(varargin)
         if (nargin == 0)
            % For randi('ClassName')
            r = Color('RGB',randi(255,[1,3]));
         elseif any([varargin{2:end}] <= 0)
            % For randi with any dimension <= 0
            r = Color.empty(varargin{2:end});
         else
            % For randi(max,m,n,...,'ClassName')
            if numel([varargin{:}]) < 2
               error('Not enough input arguments')
            end
            dims = [varargin{2:end}];
            r = zeros(dims,'Color');
            for k = 1:prod(dims)
               r(k) = Color('RGB',randi(varargin{1},[1,3]));
            end
         end
      end
   end
end

prototype 객체 메서드 구현

“like a prototype object” 객체로 구성된 배열을 반환하는 메서드의 목표는 클래스의 요구 사항에 따라 달라집니다. 이 Color 클래스의 경우 zerosLike 메서드는 해당 prototype 객체의 ColorSpace 속성값을 갖지만 ColorValues가 모두 0인 객체를 만듭니다.

다음은 Color 클래스에 대한 zerosLike 메서드를 구현한 것입니다. 이 구현은 다음과 같습니다.

  • zerosLike 메서드를 Hidden으로 정의합니다.

  • zeros 함수에 대한 호출에서 차원 인수가 없으면 스칼라 Color 객체를 반환합니다.

  • zeros에 대한 호출에서 차원 인수가 음수이거나 0이면 빈 배열을 반환합니다.

  • zeros에 대한 호출에 의해 지정된 차원의 Color 객체 배열을 반환합니다.

classdef Color
   ...
   methods (Hidden)
      function z = zerosLike(obj,varargin)
         if nargin == 1
            % For zeros('like',obj)
            cSpace = obj.ColorSpace;
            z = Color;
            z.ColorSpace = cSpace;
         elseif  any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'like',obj)
            if ~isscalar(obj)
               error('Prototype object must be scalar')
            end
            obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues));
            z = repmat(obj,varargin{:});
         end
      end
   end
end

전체 클래스 목록 표시

다음은 오버로드된 메서드를 가진 Color 클래스 정의입니다.

참고

실제 상황에서는 Color 클래스에 오류 검사, 컬러스페이스 변환 등이 필요합니다. 다음은 오버로드된 메서드 구현을 단순화한 것입니다.

classdef Color
   properties
      ColorValues = [0,0,0]
      ColorSpace = 'RGB'
   end
   methods
      function obj = Color(cSpace,values)
         if nargin > 0
            obj.ColorSpace = cSpace;
            obj.ColorValues = values;
         end
      end
   end
   methods (Static)
      function z = zeros(varargin)
         if (nargin == 0)
            % For zeros('ClassName')
            z = Color;
         elseif any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'ClassName')
            % Use property default values
            z = repmat(Color,varargin{:});
         end
      end
      function r = randi(varargin)
         if (nargin == 0)
            % For randi('ClassName')
            r = Color('RGB',randi(255,[1,3]));
         elseif any([varargin{2:end}] <= 0)
            % For randi with any dimension <= 0
            r = Color.empty(varargin{2:end});
         else
            % For randi(max,m,n,...,'ClassName')
            if numel([varargin{:}]) < 2
               error('Not enough input arguments')
            end
            dims = [varargin{2:end}];
            r = zeros(dims,'Color');
            for k = 1:prod(dims)
               r(k) = Color('RGB',randi(varargin{1},[1,3]));
            end
         end
      end
   end
   methods (Hidden)
      function z = zerosLike(obj,varargin)
         if nargin == 1
            % For zeros('like',obj)
            cSpace = obj.ColorSpace;
            z = Color;
            z.ColorSpace = cSpace;
         elseif  any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'like',obj)
            if ~isscalar(obj)
               error('Prototype object must be scalar')
            end
            obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues));
            z = repmat(obj,varargin{:});
         end
      end
   end
end

createArray 오버로드하기

createArray (R2024a 이후)는 오버로드 없이 대부분의 클래스를 지원합니다. 단, 클래스가 다음 조건 중 하나 이상을 충족한다면 정적 createArray 메서드를 구현하십시오.

  • 클래스에 디폴트 생성자가 없습니다.

  • 클래스가 빈 배열을 반환하는 디폴트 생성자를 가집니다.

  • 클래스가 배열의 각 인스턴스에 대해 동적으로 초기화되어야 하는 속성을 가집니다.

클래스가 인덱스 참조 값 할당을 통해 기존 객체로부터 배열을 생성하는 방법을 지원하지 않는다면 createArrayLike 메서드를 구현하십시오. 그러나 createArray는 대부분의 경우 속성값을 보존하므로 대부분의 클래스에서 createArrayLike를 오버로드할 필요가 없습니다.

createArray 함수를 오버로드하는 방법은 zeros와 유사하나, createArrayFillValue 이름-값 인수 때문에 구문이 약간 다릅니다.

구현할 createArray 메서드

메서드

함수 시그니처

메서드가 호출되는 경우

정적 createArray

function obj = createArray(dims,F). 여기서 dims는 둘 이상의 음이 아닌 정수로 구성된 행 벡터이고 FFillValue임(선택 사항)

createArray(dims,"ClassName")

createArray(dims,"ClassName", FillValue=F)

createArrayLike

function obj = createArrayLike(L,dims,F). 여기서 dims는 둘 이상의 음이 아닌 정수로 구성된 행 벡터이고, L은 prototype이고, FFillValue임(선택 사항)

createArrayLike(dims,Like=L)

createArrayLike(dims,Like=L,FillValue=F)

관련 항목