exponenta event banner

Индексирование массива объектов

Индексированная ссылка и назначение по умолчанию

Классы MATLAB ® поддерживают индексирование массива объектов по умолчанию. Многие конструкции классов не требуют изменения этого поведения.

Массивы позволяют ссылаться на элементы массива и назначать их с помощью подстрочной нотации. Эта запись определяет индексы определенных элементов массива. Например, предположим, что создаются два массива чисел (с помощью randi и конкатенация).

Создайте массив целых чисел 3 на 4 от 1 до 9:

A = randi(9,3,4)
A =

     4     8     5     7
     4     2     6     3
     7     5     7     7

Создайте массив 1 на 3 из чисел 3, 6, 9:

B = [3 6 9];

Ссылка и назначение элементов любого массива с использованием значений индекса в скобках:

B(2) = A(3,4);
B
B =
     3     7     9

При выполнении инструкции, включающей индексированную ссылку:

C = A(3,4);

MATLAB вызывает встроенный subsref для определения способа интерпретации оператора. Аналогично, если выполняется инструкция, включающая индексированное назначение:

C(4) = 7;

MATLAB вызывает встроенный subsasgn для определения способа интерпретации оператора.

Значение по умолчанию MATLAB subsref и subsasgn функции также работают с пользовательскими объектами. Например, создайте массив объектов одного класса:

for k=1:3
   objArray(k) = MyClass;
end

Ссылка на второй элемент в массиве объектов, objArray, возвращает объект, созданный при k = 2:

D = objArray(2);
class(D)
ans =

MyClass

Объект можно назначить массиву объектов одного класса или неинициализированной переменной:

newArray(3,4) = D;

Массивы объектов ведут себя как числовые массивы в MATLAB. Нет необходимости внедрять какие-либо специальные методы для обеспечения стандартного поведения массива в классе.

Общие сведения об индексировании массивов см. в разделе Индексирование массивов.

Что можно изменить

Можно изменить поведение индексированной ссылки на класс и/или назначения, реализуя методы класса, называемые subsref и subsasgn. Описание синтаксиса см. на соответствующих страницах ссылок.

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

  • Точечные нотационные вызовы методов классов

  • Ссылка на точечное обозначение и назначение, включающее свойства

  • Любое индексирование с использованием скобок '()'

  • Любое индексирование с использованием фигурных скобок '{}'

Осуществление subsref и subsasgn методы дают полный контроль над интерпретацией выражений индексирования для объектов класса. Реализация степени поведения, которую MATLAB обеспечивает по умолчанию, нетривиальна.

Изменение поведения индексирования

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

Это утверждение:

obj.Data(2,3)

Возвращает значение, содержащееся во второй строке, третьем столбце массива. Если имеется массив объектов, используйте выражение, например:

objArray(3).Data(2,3)

Этот оператор возвращает значение, содержащееся во второй строке, третьем столбце третьего элемента массива.

Измените поведение индексирования по умолчанию, если конструкция класса требует поведения, отличного от поведения по умолчанию MATLAB.

Встроенные вложенные ссылки и вложенные ссылки, вызываемые в методах

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

Например, в методе класса эта точка ссылается:

obj.Prop

вызывает встроенный subsref функция. Вызов определяемого классом subsref способ, использование:

subsref(obj,substruct('.','Prop'))

Всякий раз, когда метод требует функциональности определяемого классом subsref или subsasgn , класс должен вызывать перегруженные методы в качестве функций. Не используйте операторы, '()', '{}', или '.'.

Например, предположим, что определяется класс для представления многочлена. Этот класс имеет subsref метод, который вычисляет полином со значением независимой переменной, равным индексу. Предположим, что этот оператор определяет многочлен с его коэффициентами:

p = polynom([1 0 -2 -5]);

Выражение MATLAB для полученного многочлена:

x^3 - 2*x - 5

Это подстрочное выражение возвращает значение многочлена в x = 3:

p(3)
ans =
    16

Предположим, что эту функцию необходимо использовать в другом методе класса. Для этого вызовите subsref непосредственно функция. evalEqual метод принимает два polynom и значение, при котором вычисляются многочлены:

methods
   function ToF = evalEqual(p1,p2,x)
      % Create arguments for subsref
      subs.type = '()';
      subs.subs = {x};
      % Need to call subsref explicitly 
      y1 = subsref(p1,subs);
      y2 = subsref(p2,subs);
      if y1 == y2
         ToF = true;
      else 
         ToF = false;
      end
   end
end

Это поведение позволяет использовать стандартное индексирование MATLAB для реализации специализированного поведения. Примеры использования как встроенного, так и модифицированного классом индексирования см. в разделе Класс с измененным индексированием.

Избегайте переопределения атрибутов доступа

Поскольку subsref - метод класса, он имеет доступ к частным членам класса. Избегайте непреднамеренного предоставления доступа к частным методам и свойствам при работе с различными типами ссылок. Подумайте об этом subsref метод, определенный для класса, имеющего частные свойства, x и y:

classdef MyPlot
   properties (Access = private)
      x
      y
   end
   properties
      Maximum
      Minimum
      Average
   end
   methods
      function obj = MyPlot(x,y)
         obj.x = x;
         obj.y = y;
         obj.Maximum = max(y);
         obj.Minimum = min(y);
         obj.Average = mean(y);
      end
      function B = subsref(A,S)
         switch S(1).type
            case '.'
               switch S(1).subs
                  case 'plot'
                     % Reference to A.x and A.y call built-in subsref
                     B = plot(A.x,A.y);
                  otherwise
                     % Enable dot notation for all properties and methods
                     B = A.(S.subs);
               end
         end
      end
   end
end

Это subsref позволяет использовать точечную нотацию для создания графика с использованием имени 'plot'. Утверждение:

obj = MyPlot(1:10,1:10);
h = obj.plot;

вызывает plot и возвращает дескриптор графическому объекту.

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

obj.x
ans =

     1     2     3     4     5     6     7     8     9    10

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

Связанные темы