配列作成関数に対するクラス サポート
ユーザー クラス向けの配列作成関数の拡張
ones
や zeros
など、特定のサイズや型の配列を作成する MATLAB® 関数がいくつかあります。これらの関数の多くは、クラスでの具体的な処理に合わせてオーバーロードできます。このトピックでは、そのプロセスについて説明しています。既存の関数をオーバーロードせずにオブジェクト配列を作成するオプションについては、オブジェクト配列の作成と初期化を参照してください。
メモ
createArray
(R2024a 以降) は、オーバーロードしなくても多くのクラスの配列作成をサポートします。詳細については、createArray
を参照してください。createArray
のオーバーロードが役立つ可能性がある状況の詳細については、実装する createArray メソッドを参照してください。
任意の配列作成関数にクラスがサポートされるため、組み込みデータ型およびユーザー定義のデータ型と共有できるコードを開発できるようになります。たとえば、最初の開発期間中に、次のコード変数 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);
これらの関数に対するサポートをユーザー定義クラスに追加した後、そのクラスにも同様の構文が使用できるようになります。
使用する構文
クラスは、クラス名の構文とプロトタイプ オブジェクトの構文の両方をサポートすることができます。既定のオブジェクトの配列を作成するには、クラス名の構文を使用します。型、実数/複素数、その他のプロパティが既存のオブジェクトと同じオブジェクトの配列を作成するには、プロトタイプの構文を使用します。
配列作成関数に対するサポートの実装
配列作成関数をサポートするには、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})
プロトタイプ メソッドが存在しない場合に呼び出されるクラス名メソッド
使用するクラスがクラス名の構文を実装しているが、特定の関数に対するプロトタイプ オブジェクトの構文を実装しない場合でも、両方の構文を呼び出すことができます。たとえば、静的 zeros
メソッドのみを実装する場合、次の構文を呼び出せます。
zeros(...,'like',MyClass(...))
プロトタイプ オブジェクトの構文を呼び出す場合、MATLAB は最初に zerosLike
という名前のメソッドを検索します。MATLAB がメソッドを検出できなかった場合、zeros
静的メソッドを呼び出します。
この機能は、配列の作成にクラス名のみが必要な場合に便利です。完全な配列作成関数の構文をサポートするために、両方のメソッドを実装する必要はありません。クラス名の構文のみを実装する場合、プロトタイプ オブジェクトの構文の呼び出しは、クラス名の構文の呼び出しと同じです。
全関数入力のサポート
配列作成関数の入力引数には、関数が返す配列の次元や、必要に応じてその他の引数も含めることができます。一般に、メソッドがサポートしなければならない 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
クラスは、RGB
や HSV
など、特定の色空間における色を表します。クラス名メソッドの実装とプロトタイプ オブジェクト メソッドの実装の説明では、オーバーロード メソッドを実装するための基本としてこのクラスを使用しています。
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
クラスの場合、zerosLike
メソッドはプロトタイプ オブジェクトの 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 以降) は、オーバーロードしなくてもほとんどのクラスをサポートします。ただし、クラスが次の条件の 1 つ以上に当てはまる場合は静的 createArray
メソッドを実装します。
クラスに既定のコンストラクターがない。
クラスの既定のコンストラクターが空の配列を返す。
クラスのプロパティを配列の各インスタンスで動的に初期化する必要がある。
クラスがインデックス付き代入による既存オブジェクトからの配列作成をサポートしていない場合は、createArrayLike
メソッドを実装します。ただし、通常は createArray
でプロパティ値の保持がサポートされるため、ほとんどのクラスでは createArrayLike
をオーバーロードする必要はありません。
関数 createArray
をオーバーロードするプロセスは zeros
と同様ですが、構文が少し異なります。これは、createArray
の名前と値の引数 FillValue
によるものです。
実装する createArray
メソッド
メソッド | 関数シグネチャ | メソッドの呼び出し時 |
---|---|---|
静的 |
|
|
|
|
|