Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

numArgumentsFromSubscript

カスタマイズされたインデックス手法の引数の数

説明

n = numArgumentsFromSubscript(obj,s,indexingContext) は、subsasgn への必要な入力数または subsref からの必要な出力数を返します。

返されたインデックス式から出力される値の数や、コンマ区切りのリストに代入する値の数を記述するには、numArgumentsFromSubscript をオーバーロードします。これは、'{}' または '.' インデックスで終了するインデックス式です。関数 numArgumentsFromSubscript を使用すると、次のような処理ができます。

  • インデックス式に使用されるインデックス演算とインデックスにアクセスする

  • インデックス演算が参照ステートメント、関数に渡された式、あるいは代入のどのコンテキストで処理されるかを判別する

クラスが numArgumentsFromSubscript をオーバーロードする場合、MATLAB® がこれを呼び出して、要素数が 1 より大きい場合にインデックス演算に使用される配列要素の数を判別します。たとえば、次の '.' インデックス演算では numArgumentsFromSubscript の呼び出しが行われます。

  • objArray.a — ステートメント (Statement) で参照される要素の数

  • func(objArray.a) — 式で返される要素の数 (Expression)

  • [objArray.a] = rhs — コンマ区切りのリスト (Assignment) で代入される値の数

MATLAB は、呼び出しコンテキストを使用して numArgumentsFromSubscript で返された値を適用するかどうかを判断します。numArgumentsFromSubscript の実装方法によって、3 種類のインデックス付けステートメントにそれぞれ異なる出力を提供できます。たとえば、numArgumentsFromSubscript のこのオーバーロードでは次が行われます。

  • 関数に渡されるインデックス式について subsref からの出力引数の想定される数を変更します。

  • インデックス演算に必要な引数の数を判別するには、インデックス付けサブ構造体 s を使用します。

function n = numArgumentsFromSubscript(obj,s,indexingContext)
   if indexingContext == matlab.mixin.util.IndexingContext.Expression
      n = 1;
   else
      n = length(s(1).subs{:});
   end
end

subsref メソッドを varargout 出力を使って実装し、MATLAB が指定された出力引数の数を使用してこのメソッドを呼び出せるようにします。

function varargout = subsref(obj,s)
   ...
end

すべて折りたたむ

オブジェクト プロパティのインデックスとして単語を使用します。

既定では、MATLAB は文字配列内の各文字を個別の要素として扱います。したがって、MATLAB は、文字配列のインデックスを複数のインデックス値として解釈します。

numArgumentsFromSubscript をオーバーロードしない場合、キーワード インデックス付けのステートメントが要求する引数が subsref および subsasgn メソッドに対して過多になります。文字配列を 1 つのキーワードとして使用するインデックス付けを実装するには、参照または代入される要素数として 1 を返す numArgumentsFromSubscript メソッドを定義します。

numArgumentsFromSubscript をオーバーロードして、以下のようなインデックス付きの参照および代入をサポートします。

文字配列を使用したインデックス参照:

obj{'keyword'}

関数の引数でのインデックス参照:

func(obj{'keyword'})

オブジェクト配列へのコンマ区切りリストの代入:

[obj{'keyword'}] = right-side values;

このような場合、subsrefsubsasgn は、呼び出しコンテキストに基づいて必要な出力引数および入力引数の数を判別することができません。この情報は関数 numArgumentsFromSubscript を使用して提供します。

2 つのプロパティをもつクラス KeyIndex を定義します。KeyCell にはキーの名前を格納し、DataArray には対応するデータを格納します。インデックス付けをカスタマイズするには、次を行います。

  • 指定のキーワードに対応するデータ値を返す subsref メソッドを実装します。

  • 指定の値を DataArray プロパティの対応する要素に代入する subsasgn メソッドを実装します。

  • numArgumentsFromSubscript をオーバーロードして、1 の値か、オブジェクト配列の場合はスカラー オブジェクトと numel(objArray) の値を返します。

月の名前を含む cell 配列を KeyCell プロパティとして指定します。DataArray プロパティに、それぞれ対応する月の降雪量を示す数値配列を指定します。

snow15 = KeyIndex({'Jan','Feb','March'},[36 42 2])
snow15 = 

  KeyIndex with properties:

      KeyCell: {'Jan'  'Feb'  'March'}
    DataArray: [36 42 2]

キーワードを使用して、特定の月の降雪量を参照します。

snow15{'Feb'}
ans =

    42

'{}' インデックス付けでキーワードを使用して、対応する要素に代入します。

snow15{'Feb'} = 52;

すると、キー 'Feb' に対応する値が変更されます。

snow15{'Feb'}
ans =

    52

2 年間の降雪量データを含む配列を作成します。

snow14 = KeyIndex({'Jan','Feb','March'},[12 8 2]);
sTotal = [snow14,snow15];

各年度の 2 月の降雪量を求めます。

sTotal{'Feb'}
ans =

     8


ans =

    52

両方の年度の 2 月の降雪量の値を更新します。cell 配列内のインデックス付けにより、コンマ区切りリストが返されます。

c{1} = 34;
c{2} = 56;
[sTotal{'Feb'}] = c{:};

KeyIndex クラスは次のようになります。このクラスは特定のプログラミング手法を示すものです。通常のクラスで必要とされるエラー検査やその他の機能は含まれていません。

classdef KeyIndex
   properties
      KeyCell
      DataArray
   end
   methods
      function obj = KeyIndex(key,data)
         if nargin > 0
            obj.KeyCell = key;
            obj.DataArray = data;
         end
      end
      function n = numArgumentsFromSubscript(obj,~,~)
         n = numel(obj);
      end
      function varargout = subsref(obj,s)
         a = numel(obj);
         switch s(1).type
            case '{}'
               varargout = cell(1,a);
               for j = 1:a
                  for k = 1:numel(obj(j).KeyCell)
                     if strcmp(s.subs(:),obj(j).KeyCell{k})
                        varargout{j} = obj(j).DataArray(k);
                     end
                  end
               end
            case '.'
               varargout = {builtin('subsref',obj,s)};
            case '()'
               varargout = {builtin('subsref',obj,s)};
         end
      end
      function obj = subsasgn(obj,s,varargin)
         a = numel(varargin);
         switch s(1).type
            case '{}'
               for j = 1:a
                  for k = 1:numel(obj(j).KeyCell)
                     if strcmp(s.subs(:),obj(j).KeyCell{k})
                        obj(j).DataArray(k) = varargin{j};
                     end
                  end
               end
            case '.'
               obj = builtin('subsasgn',obj,s,varargin{:});
            case '()'
               obj = builtin('subsasgn',obj,s,varargin{:});
         end
      end
   end
end

要素や配列ごとのプロパティのインデックス付けをサポートするクラスを定義します。

関数 numArgumentsFromSubscript により、クラスで特定のプロパティへの参照をカスタマイズできるようになります。numArgumentsFromSubscript に渡されるインデックス付けサブ構造体引数 (s) には、ドット インデックス式で参照されるプロパティの名前 (つまり obj.PropertyName という形式の参照) を含めます。numArgumentsFromSubscript はこのインデックス付けサブ構造体を使用して、任意のプロパティについて一意の値を返すことができます。

PerArray クラスは、インデックス付けサブ構造体の情報を使用して、各プロパティ参照の出力の数を指定します。

numArgumentsFromSubscript をオーバーロードして次を返します。

  • ByElement プロパティの値のコンマ区切りリスト。配列の各要素につき 1 つの値を返します。

  • 配列全体につき、単一の ByArray プロパティ値。

PerArray オブジェクトの配列を作成します。

for k = 1:4
   pa(k) = PerArray(rand(k));
end

プロパティ値のコンマ区切りリストを返すには、ByElement プロパティをクエリします。

pa.ByElement
ans =

    0.7513


ans =

    0.2551    0.6991
    0.5060    0.8909


ans =

    0.9593    0.1493    0.2543
    0.5472    0.2575    0.8143
    0.1386    0.8407    0.2435


ans =

    0.9293    0.6160    0.5853    0.7572
    0.3500    0.4733    0.5497    0.7537
    0.1966    0.3517    0.9172    0.3804
    0.2511    0.8308    0.2858    0.5678

配列全体に対して 1 つの値を返すには、ByArray プロパティをクエリします。

pa.ByArray
ans =

    3.1416

PerArray クラスは次のようになります。このクラスは特定のプログラミング手法を示すものです。通常のクラスで必要とされるエラー検査やその他の機能は含まれていません。

classdef PerArray
   properties
      ByElement
   end
   properties (Constant)
      ByArray = pi;
   end
   methods
      function obj = PerArray(be)
         if nargin > 0
            obj.ByElement = be;
         end
      end
      function n = numArgumentsFromSubscript(obj,s,indexingContext)
         import matlab.mixin.util.IndexingContext
         if (indexingContext ~= IndexingContext.Assignment)
            if length(s) < 2
               switch (s.subs(:)')
                  case 'ByElement'
                     n = numel(obj);
                  case 'ByArray'
                     if strcmp(s(1).type,'.')
                        n = 1;
                     end
               end
            elseif length(s) > 1
               n = length([s(1).subs{:}]);
            end
         end
      end
      function varargout = subsref(obj,s)
         
         switch s(1).type
            case '.'
               varargout = cell(1,numel(obj));
               for k = 1:numel(obj)
                  varargout{k} = obj(k).(s.subs(:));
               end
            case '()'
               if length([s(1).subs{:}]) > 1
                  ind = [s(1).subs{:}];
                  numInd = length(ind);
                  varargout = cell(1,numInd);
                  for k = 1:numInd
                     varargout{k} = obj(ind(k)).(s(2).subs(:));
                  end
               else
                  varargout = {builtin('subsref',obj,s)};
               end
         end
      end
   end
end

入力引数

すべて折りたたむ

インデックス演算で使用されるオーバーロード クラスのオブジェクト。このオブジェクトのクラスによって、インデックス演算の結果として MATLAB が呼び出す subsref または subsasgn メソッドが決まります。

特定のインデックス式に関する情報を含む、インデックス付け構造体またはインデックス付け構造体の配列。各構造体には 2 つのフィールドがあります。

  • type — インデックス式は '()''{}''.' のいずれかを使用できます。

  • subs — 添字の値 (プロパティ名またはインデックス番号の cell 配列)

データ型: struct

結果が適用されるコンテキスト。次のいずれかの列挙値として指定します。

  • matlab.mixin.util.IndexingContext.Statement — ステートメントとして使用されるインデックス付き参照 (obj.a)

  • matlab.mixin.util.IndexingContext.Expression — 関数の引数として使用されるインデックス付き参照 (func(obj.a))

  • matlab.mixin.util.IndexingContext.Assignment — インデックス付き代入 ([obj.a] = x)

出力引数

すべて折りたたむ

オーバーロードされる subsref で返される引数の数か、オーバーロードされる subsasgn に渡される引数の数。numArgumentsFromSubscript をオーバーロードして、そのクラスで各種のインデックス付けシナリオに必要とされる値を返します。

ヒント

  • オーバーロードされた subsref および subsasgn からの結果を制御するには、numel の代わりに numArgumentsFromSubscript をオーバーロードします。numArgumentsFromSubscript をオーバーロードすることで、numel のオーバーロードに起因するエラーを回避できます。

R2015b で導入