Шаблоны кода для методов 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];

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

  • 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

Следующая среда для 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.

Похожие темы