Шаблоны кода для 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)

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

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

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

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

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

  • subschar вектор с именем свойства или массивом ячеек индексов, используемых в выражении, включая : и 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{:});

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.

Похожие темы