Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

配列作成関数に対するクラス サポート

ユーザー クラス向けの配列作成関数の拡張

oneszeros など、特定のサイズや型の配列を作成する MATLAB® 関数がいくつかあります。ユーザー定義クラスには、オーバーロード メソッドの構文を使用する必要なしに、配列作成関数のサポートを追加できます。

任意の配列作成関数にクラスがサポートされるため、組み込みデータ型およびユーザー定義のデータ型と共有できるコードを開発できるようになります。たとえば、最初の開発期間中に、次のコード変数 x のクラスを組み込み型に設定し、その後 zeros を透過的にオーバーロードするユーザー定義クラスで置き換えることもできます。

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

配列作成関数は、次の 2 つの方法で特定の型の配列を作成します。

  • クラス名の構文 — 配列要素の型を特定するクラス名を指定します。

  • プロトタイプ オブジェクトの構文 — 配列の要素型と他の特性を決定するために関数が使用するプロトタイプ オブジェクトを指定します。

以下に例を示します。

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);

これらの関数に対するサポートをユーザー定義クラスに追加した後、そのクラスにも同様の構文が使用できるようになります。

使用する構文

既定のオブジェクトの配列を作成する場合は、コンストラクターに入力引数を指定する必要がないため、クラス名の構文を使用します。

特定のプロパティ値をもつオブジェクトの配列を作成するか、コンストラクターが他の入力を必要とする場合は、プロトタイプ オブジェクトを使用してこの情報を提供します。

クラスは、クラス名の構文とプロトタイプ オブジェクトの構文の両方をサポートすることができます。

関数 true と関数 false でクラス名の構文を実装することができます。ただし、既定ではこれらの関数はその構文をサポートしません。

プロトタイプ メソッドが存在しない場合に呼び出されるクラス名メソッド

使用するクラスがクラス名の構文を実装しているが、特定の関数に対するプロトタイプ オブジェクトの構文を実装しない場合でも、両方の構文を呼び出すことができます。たとえば、静的 zeros メソッドのみを実装する場合、次の構文を呼び出せます。

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

プロトタイプ オブジェクトの構文を呼び出す場合、MATLAB は最初に zerosLike という名前のメソッドを検索します。MATLAB がメソッドを検出できなかった場合、zeros 静的メソッドを呼び出します。

この機能は、配列の作成にクラス名のみが必要な場合に便利です。完全な配列作成関数の構文をサポートするために、両方のメソッドを実装する必要はありません。クラス名の構文のみを実装する場合、プロトタイプ オブジェクトの構文の呼び出しは、クラス名の構文の呼び出しと同じです。

配列作成関数に対するサポートの実装

配列作成関数をサポートするには、2 つの異なるメソッドを使用します。一方のメソッドはクラス名の構文を実装し、他方のメソッドはプロトタイプ オブジェクトの構文を実装します。

たとえば、関数 zeros をサポートするには、次のようにします。

  • クラス名の構文を

    zeros(...,'ClassName')

    Static メソッドとして実装します。

    methods (Static)
       function z = zeros(varargin)
          ...
       end
    end
  • プロトタイプ オブジェクトの構文は、

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

    char ベクトル 'Like' が名前に付加された Hidden メソッドとして実装します。

    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})

全関数入力のサポート

配列作成関数の入力引数には、関数が返す配列の次元や、必要に応じてその他の引数も含めることができます。一般に、メソッドがサポートしなければならない 3 つのケースがあります。

  • 次元の入力引数が存在せず、結果としてスカラーが返される。以下に例を示します。

    z = zeros('MyClass');
  • 1 つ以上の次元が 0 以下であり、結果として空配列になる。以下に例を示します。

    z = zeros(2,0,'MyClass');
  • 任意の数の有効な配列次元が配列のサイズを指定している。以下に例を示します。

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

配列作成関数がクラス メソッドを呼び出す際、クラス名またはリテラル 'like' を除く、入力引数とオブジェクト変数をメソッドに渡します。メソッドは次のシグネチャを使って実装できます。

  • 「クラス名」メソッドの場合: zeros(varargin)

  • 「like を指定したプロトタイプ オブジェクト」メソッドの場合: zeros(obj,varargin)

サンプル クラス

Color クラスは、RGBHSV など、特定の色空間における色を表します。クラス名メソッドの実装プロトタイプ オブジェクト メソッドの実装の説明では、オーバーロード メソッドを実装するための基本としてこのクラスを使用しています。

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

プロトタイプ オブジェクト メソッドの実装

"like" を指定したプロトタイプ オブジェクトなど、オブジェクトの配列を返すメソッドの目的は、クラスの必要条件によって異なります。Color クラスの場合、zeroLike メソッドはプロトタイプ オブジェクトの 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

関連するトピック