Шаблоны кода для subsref и subsasgn Методов

Настройка индексируемой ссылки и присвоения

Пользовательские классы имеют те же поведения индексации как тот из встроенных классов. Классы могут настроить операции индексации путем перегрузки функций, которые MATLAB® вызывает, чтобы выполнить выражения индексации. Перегрузите subsref и функции subsasgn когда это необходимо, чтобы задать специальные поведения для индексируемой ссылки и присвоения.

Для обзора объектной индексации смотрите, что Объектный массив Индексирует.

Синтаксис для subsref и subsasgn Методы

MATLAB вызывает subsref и методы subsasgn вашего класса с этими аргументами.

МетодВходной параметрВывод

b = subsref(obj,s)

  • obj — Объект или объектный массив используются в индексации выражения

  • s Индексация структуры

b Результат индексации выражения

obj = subsasgn(obj,s,b)

  • obj — Объект или объектный массив используются в индексации выражения

  • s Индексация структуры

  • b Значение присвоено

obj — Объект или объектный массив после присвоения

Изменение число аргументов

Если ваш проект класса требует, чтобы индексирующие операции возвратили или присвоили различный номер значений, чем номер, заданный операцией индексации значения по умолчанию, перегрузили функцию numArgumentsFromSubscript, чтобы управлять nargout для subsref и nargin для subsasgn. Для получения дополнительной информации и примеры, смотрите numArgumentsFromSubscript.

Индексация структуры описывает выражения индексации

Структура индексации содержит информацию, которая описывает выражение индексации. Методы класса используют информацию в структуре индексации, чтобы выполнить выражение и реализовать пользовательское поведение.

Например, класс CustomIndex задает свойство, которое можно использовать в индексации выражений.

classdef CustomIndex
   properties
      DataArray
   end
end

Создайте объект и присвойте матрицу 5 на 5, созданную функцией magic к свойству DataArray.

a = CustomIndex;
a.DataArray = magic(5);

Это преобразованное в нижний индекс ссылочное выражение возвращает первую строку матрицы 5 на 5.

a.DataArray(1,:)
ans =

    17    24     1     8    15

Это выражение присваивает новые значения первой строке массива, сохраненного в свойстве DataArray.

a.DataArray(1,:) = [1 2 3 4 5];

Этот оператор присваивания использование:

  • Ссылка типа '.'

  • Имя свойства после точки (то есть, DataArray)

  • Область значений индексов (1,:) в круглых скобках

Структура индексации содержит эту информацию в полях type и subs.

Значения структуры индексации

При выполнении выражения индексации MATLAB вызывает класс subsref или метод subsasgn, если класс перегружает эти функции. Один из аргументов, переданных методу, является структурой индексации. Структура индексации имеет два поля:

  • ввод Один из трех возможных типов индексации: '.', '()', '{}'

  • subs — Вектор char с именем свойства или массивом ячеек индексов, используемых в выражении, включая : и end.

Если выражение индексации является составным выражением, то MATLAB передает массив структур, одного struct для каждого уровня индексации. Например, в этом выражении:

a.DataArray(1,:)

массив структур индексации S имеет эти значения:

  • S(1).type установлен в '.', указав, что первая операция индексации является точкой.

  • s(1).subs установлен в имя свойства, 'DataArray'

Второй уровень индексации в своей стихии структуры индексации:

  • S(2).types установлен в '()', указывающий, что вторая операция индексации является индексацией круглых скобок

  • S(2).subs установлен в массив ячеек, содержащий индексы {[1],[:]}

Типичные шаблоны для методов индексирования

Перегружать функции subasgn и subsref:

  • Определите полное выражение индексации с помощью полей types и subs структуры индексации.

  • Реализуйте специализированные поведения для операций индексации, поддержанных классом.

  • Возвратите соответствующие значения или измененные объекты в ответ на вызов MATLAB.

Оператор switch является удобным способом обнаружить первый уровень индексации. Существует три типа индексации — точка, круглые скобки и фигурные скобки. Каждый блок case в операторе switch реализует все выражения индексации, которые начинаются с того типа первого уровня индексации.

Методы должны реализовать все выражения индексации, которые поддерживает класс. Если вы не настраиваете конкретный тип индексации, вызовите встроенную функцию, чтобы обработать то выражение.

Используйте длину массива структур индексации, и индексация типа задают условные операторы для составных выражений индексации.

Среда кода для subsref Метода

Следующая среда для метода subsref показывает, как использовать информацию в структуре индексации в условных операторах. Ваше приложение может включить другое выражение, не показанное здесь.

function varargout = subsref(obj,s)
   switch s(1).type
      case '.'
         if length(s) == 1
            % Implement obj.PropertyName
            ...
         elseif length(s) == 2 && strcmp(s(2).type,'()')
            % Implement obj.PropertyName(indices)
            ...
         else
            [varargout{1:nargout}] = builtin('subsref',obj,s);
         end
      case '()'
         if length(s) == 1
            % Implement obj(indices)
            ...
         elseif length(s) == 2 && strcmp(s(2).type,'.')
            % Implement obj(ind).PropertyName
            ...
         elseif length(s) == 3 && strcmp(s(2).type,'.') && strcmp(s(3).type,'()')
            % Implement obj(indices).PropertyName(indices)
            ...
         else
            % Use built-in for any other expression
            [varargout{1:nargout}] = builtin('subsref',obj,s);
         end
      case '{}'
         if length(s) == 1
            % Implement obj{indices}
            ...
         elseif length(s) == 2 && strcmp(s(2).type,'.')
            % Implement obj{indices}.PropertyName
            ...
         else
            % Use built-in for any other expression
            [varargout{1:nargout}] = builtin('subsref',obj,s);
         end
      otherwise
         error('Not a valid indexing expression')
   end

Используя varargout для возвращенного значения позволяет методу работать с массивами объектов. Например, предположите, что вы хотите поддержать возврат списка, разделенного запятыми с выражением как этот:

[x1,...xn] = objArray.PropertyName(Indices)

Это выражение приводит к двухэлементному массиву структур индексации. Тип первого уровня является точкой ('.'), и второй уровень является круглыми скобками ('()'). Создайте массив ячеек varargout с каждым значением в массиве.

case '.'
   ...
   if length(s)==2 && strcmp(s(2).type,'()')
      prop = s(1).subs;      % Property name
      n = numel(obj);        % Number of elements in array
      varargout = cell(1,n); % Preallocate cell array
      for k = 1:n
         varargout{k} = obj(k).(prop).(s(2).subs);
      end
   end
   ...
end

шаблон subsasgn

Следующая среда для метода subsasgn показывает, как использовать структуру индексации в условных операторах то присвоение реализации операции.

function obj = subsasgn(obj,s,varargin)
   switch s(1).type
      case '.'
         if length(s) == 1
            % Implement obj.PropertyName = varargin{:};
            ...
         elseif length(s) == 2 && strcmp(s(2).type,'()')
            % Implement obj.PropertyName(indices) = varargin{:};
            ...
         else
            % Call built-in for any other case
            obj = builtin('subsasgn',obj,s,varargin{:});
         end
      case '()'
         if length(s) == 1
            % Implement obj(indices) = varargin{:};
         elseif length(s) == 2 && strcmp(s(2).type,'.')
            % Implement obj(indices).PropertyName = varargin{:};
            ...
         elseif length(s) == 3 && strcmp(s(2).type,'.') && strcmp(s(3).type,'()')
            % Implement obj(indices).PropertyName(indices) = varargin{:};
            ...
         else
            % Use built-in for any other expression
            obj = builtin('subsasgn',obj,s,varargin{:});
         end       
      case '{}'
         if length(s) == 1
            % Implement obj{indices} = varargin{:}
            ...
         elseif length(s) == 2 && strcmp(s(2).type,'.')
            % Implement obj{indices}.PropertyName = varargin{:}
            ...
            % Use built-in for any other expression
            obj = builtin('subsasgn',obj,s,varargin{:});
         end
      otherwise
         error('Not a valid indexing expression')
   end
end

Используя varargin для значения правой стороны оператора присваивания позволяет методу работать с массивами объектов. Например, предположите, что вы хотите поддержать присвоение списка, разделенного запятыми с выражением как этот:

C = {'one';'two';'three'};
[objArray.PropertyName] = C{:}

Это выражение результаты в структуре индексации с точечным типом ('.'), индексирующий массив ячеек C на правой стороне оператора присваивания, производит список, разделенный запятыми. Этот код присваивает один элемент списка каждому свойству в объектном массиве.

case '.'
   if length(s)==1
      prop = s(1).subs;      % Property name
      n = numel(obj);        % Number of elements in array
      for k = 1:n
         obj(k).(prop) = varargin{k};
      end
   end
end

Похожие темы