Индексация объектных массивов

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

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.

Встроенные subsref и subsasgn вызываются в методах

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 функция непосредственно. The 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 и возвращает указатель в графический объект.

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

obj.x
ans =

     1     2     3     4     5     6     7     8     9    10

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

Похожие темы