Пользовательские классы имеют то же поведение индексации, что и встроенные классы. Классы могут настраивать операции индексации путем перегрузки функций MATLAB® вызывается для вычисления выражений индексации. Перегрузите subsref и subsasgn функции, когда необходимо задать специальное поведение для индексированной ссылки и назначения.
Обзор индексации объектов см. в разделе Индексация объектных массивов.
MATLAB вызывает subsref и subsasgn методы вашего класса с этими аргументами.
| Метод | Вход | Выход |
|---|---|---|
|
|
|
|
|
|
Если ваш проект класса требует, чтобы операции индексации возвращали или назначали другое количество значений, чем число, заданное операцией индексации по умолчанию, перегрузите 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];
Этот оператор назначения использует:
A '.' ссылка на тип
Имя свойства, следующего за точкой (то есть DataArray)
A области значений индексов (1,:) в круглых скобках
Структура индексации содержит эту информацию в type и subs поля.
При выполнении выражения индексации MATLAB вызывает subsref класса или subsasgn метод, если класс перегружает эти функции. Одним из аргументов, переданных в метод, является структура индексации. Структура индексации состоит из двух полей:
type - Один из трех возможных типов индексации: '.', '()', '{}'
subs - A char вектор с именем свойства или массив ячеек индексов, используемых в выражении, включая : и end.
Если выражение индексации является составным выражением, то MATLAB передает массив структур, единицу struct для каждого уровня индексации. Для примера в этом выражении:
a.DataArray(1,:)
массив структуры индексации S имеет следующие значения:
S(1).type установлено в '.', что указывает, что первая операция индексации является точкой.
s(1).subs задано имя свойства, 'DataArray'
Второй уровень индексации находится во втором элементе структуры индексации:
S(2).types установлено в '()' указание второй операции индексации на индексацию в круглых скобках
S(2).subs задан массив ячеек, содержащий индексы {[1],[:]}
Чтобы перегрузить subsref и subasgn функции:
Определите полное выражение индексации с помощью types и subs поля структуры индексации.
Реализуйте специализированное поведение для операций индексации, поддерживаемых классом.
Возвращает соответствующие значения или измененные объекты в ответ на вызов MATLAB.
A 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 метод показывает, как использовать структуру индексации в условных операторах, которые реализуют операции назначения.
function obj = subsasgn(obj,s,varargin) % Allow subscripted assignment to uninitialized variable if isequal(obj,[]) % obj = ClassName.empty; end 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
Назначение элементу неинициализированной переменной приводит к вызову subsasgn метод класса на правой стороне назначения. Для примера этот класс задает subsasgn метод, который просто вызывает встроенный subsasgn СПОСОБ ИНДЕКСАЦИИ КРУГЛЫХ СКОБОК.
classdef MyClass methods function obj = subsasgn(obj,s,varargin) switch s(1).type case '()' obj = builtin('subsasgn',obj,s,varargin{:}); end end end end
При попытке назначить объект MyClass к первому элементу неинициализированной переменной, B(1) в следующем операторе MATLAB вызывает subsasgn метод MyClass с пустой двойкой ([]) как первый аргумент. Назначение может вызвать ошибку, поскольку subsasgn метод должен быть передан объекту класса.
clear B
B(1) = MyClass;The following error occurred converting from MyClass to double:
Conversion to double from MyClass is not possible.
Error in MyClass/subsasgn (line 6)
obj = builtin('subsasgn',obj,s,varargin{:});The subsasgn метод может обнаружить эту ситуацию и предпринять соответствующее действие, например, вернуть полезное сообщение об ошибке, если класс не поддерживает этот тип назначения, или преобразовать вход в объект класса и передать его в subsasgn.
Для примера, потому что MyClass может разрешить подписанное назначение неинициализированной переменной, subsasgn метод может изменить первый аргумент с пустого двойника на пустой MyClass объект.
Используйте isequal функцию для проверки входа и empty статический метод для создания пустого объекта.
classdef MyClass methods function obj = subsasgn(obj,s,varargin) if isequal(obj,[]) obj = MyClass.empty; end obj = builtin('subsasgn',obj,s,varargin{:}); end end end
Подписанное назначение неинициализированной переменной теперь избегает предыдущей ошибки.
clear B
B(1) = MyClass;
B = MyClass with no properties.