exponenta event banner

Класс с измененным индексированием

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

В этом примере определяется класс, который изменяет поведение индексирования по умолчанию путем реализации subsref и subsasgn методы. Класс также реализует преобразование типа и добавление посредством реализации double метод преобразователя и plus способ.

Целью проектирования класса является:

  • Позволяет рассматривать объект класса как числовой массив

  • Иметь возможность содержать нечисловые и числовые данные в объекте класса

Описание класса

Класс имеет три свойства:

  • Data - числовые данные испытаний

  • Description - описание данных испытаний

  • Date - проведена проверка даты

Предположим, что у вас есть следующие случайные данные (randi):

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

     8     9     3     9
     9     6     5     2
     2     1     9     9

Создайте экземпляр класса:

obj = MyDataClass(d,'Test001')
obj = 

  MyDataClass with properties:

           Data: [3x4 double]
    Description: 'Test001'
           Date: [2012 1 7 9 32 34.5190]

Аргументы конструктора передают значения для Data и Description свойства. clock функция присваивает значение Date из конструктора. Этот подход позволяет получить информацию о времени и дате создания каждого экземпляра.

Вот предварительный список кодов без subsref, subsasgn double, и plus методы.

classdef MyDataClass
   properties
      Data
      Description
   end
   properties (SetAccess = private)
      Date
   end
   methods
      function obj = MyDataClass(data,desc)
         if nargin > 0
            obj.Data = data;
         end
         if nargin > 1
            obj.Description = desc;
         end
         obj.Date = clock;
      end
   end
end

Специализированная подстрочная ссылка - вложенная ссылка

Реализация subsref для поддержки как стандартного, так и специализированного типа индексирования.

  • Поведение индексированной ссылки по умолчанию для скалярных объектов:

    obj.Data(2,3)
    ans =
    
         5
  • И добавить функциональность для индексирования в Data свойство с выражением, подобным этой инструкции:

    obj(2,3)
    

При переопределении '()' индексирование для поддержки доступа к Data свойство, невозможно создать массивы MyDataClass объекты и использование '()' индексирование для доступа к отдельным объектам. Можно ссылаться только на скалярные объекты.

Для достижения целей проектирования, subsref метод должен обрабатывать все типы индексирования. subsref способ:

  • Вызывает builtin subsref функция для '.' индексация

  • Возвращает ошибку для '{}' индексация

  • Определяет собственную версию '()' индексирование.

Результат: obj(i) эквивалентно obj.Data(i).

function sref = subsref(obj,s)
   % obj(i) is equivalent to obj.Data(i)
   switch s(1).type
      case '.'
         sref = builtin('subsref',obj,s);
      case '()'
         if length(s) < 2
            sref = builtin('subsref',obj.Data,s);
         else
            sref = builtin('subsref',obj,s);
         end
      case '{}'
         error('MYDataClass:subsref',...
            'Not a supported subscripted reference')
   end
end

Специализированное назначение по подписке - subsasgn

Чтобы поддерживать эквивалент поведения индексированной ссылки с индексированным назначением, реализуйте subsasgn способ.

  • Поддержка индексированного назначения по умолчанию:

    obj.Data(2,3) = 9;
  • Добавьте функциональные возможности для назначения значений Data свойство с выражением, подобным этой инструкции:

    obj(2,3) = 9;

Как и subsref способ, subsasgn способ:

  • Вызывает builtin subsasgn функция для '.' индексация

  • Возвращает ошибку для '{}' индексация

  • Определяет собственную версию '()' индексирование.

substruct функция переопределяет тип индекса и структуру индексных индексов, которые MATLAB ® передает subsref и subsasgn.

function obj = subsasgn(obj,s,val)
   if isempty(s) && isa(val,'MyDataClass')
      obj = MyDataClass(val.Data,val.Description);
   end
   switch s(1).type
      case '.'
         obj = builtin('subsasgn',obj,s,val);
      case '()'
         if length(s)<2
            if isa(val,'MyDataClass')
               error('MyDataClass:subsasgn',...
                  'Object must be scalar')
            elseif isa(val,'double')
               % Redefine the struct s to make the call: obj.Data(i)
               snew = substruct('.','Data','()',s(1).subs(:));
               obj = subsasgn(obj,snew,val);
            end
         end
      case '{}'
         error('MyDataClass:subsasgn',...
            'Not a supported subscripted assignment')
   end
end

Внедрение добавления для объектных данных - дважды и плюс

Во-первых, реализовать double метод, преобразующий объект в массив двойников. Путем реализации double метод конвертера, можно добавить MyDataClass объект другому классу объектов. Однако другой класс должен реализовать double метод, который также возвращает массив двойников. Дополнительные сведения о преобразовании типов см. в разделе Преобразователи объектов.

Разрешить прямое добавление Data значения свойств путем реализации plus способ. Реализация plus способ позволяет использовать + оператор для добавления MyDataClass объекты.

Поскольку метод plus реализует сложение путем добавления двойных массивов, MATLAB:

  • Применять правила добавления при добавлении MyDataClass объекты

  • Возвращает ошибки для любого условия, которое может привести к ошибкам в числовом сложении по умолчанию. Например, несоответствие размеров.

plus метод использует double метод преобразования объекта в числовые значения перед выполнением сложения:

function a = double(obj)
   a = obj.Data;
end
function c = plus(obj,b)
   c = double(obj) + double(b);
end

Например, plus метод позволяет добавить скалярное число к объекту Data массив.

Вот значения Data, отображается с использованием индексированной ссылки:

obj(:,:)
ans =

     8     9     3     9
     9     6     9     2
     2     1     9     9

Добавить 7 к массиву, содержащемуся в Data свойство:

obj + 7
ans =

    15    16    10    16
    16    13    16     9
     9     8    16    16

MyDataClass.m

Это определение для MyDataClass включает в себя end метод индексирования, обсуждаемый в конце как индекс объекта. посторонний

classdef MyDataClass
   % Example for "A Class with Modified Indexing"
   properties
      Data
      Description
   end
   properties (SetAccess = private)
      Date
   end
   methods
      function obj = MyDataClass(data,desc)
         % Support 0-2 args
         if nargin > 0
            obj.Data = data;
         end
         if nargin > 1
            obj.Description = desc;
         end
         obj.Date = clock;
      end
      
      function sref = subsref(obj,s)
         % obj(i) is equivalent to obj.Data(i)
         switch s(1).type
            case '.'
               sref = builtin('subsref',obj,s);
            case '()'
               if length(s)<2
                  sref = builtin('subsref',obj.Data,s);
               else
                  sref = builtin('subsref',obj,s);
               end
            case '{}'
               error('MyDataClass:subsref',...
                  'Not a supported subscripted reference')
         end
      end
      
      function obj = subsasgn(obj,s,val)
         if isempty(s) && isa(val,'MyDataClass')
            obj = MyDataClass(val.Data,val.Description);
         end
         switch s(1).type
            case '.'
               obj = builtin('subsasgn',obj,s,val);
            case '()'
               %
               if length(s)<2
                  if isa(val,'MyDataClass')
                     error('MyDataClass:subsasgn',...
                        'Object must be scalar')
                  elseif isa(val,'double')
                     snew = substruct('.','Data','()',s(1).subs(:));
                     obj = subsasgn(obj,snew,val);
                  end
               end
            case '{}'
               error('MyDataClass:subsasgn',...
                  'Not a supported subscripted assignment')
         end
      end
      
      function a = double(obj)
         a = obj.Data;
      end
      
      function c = plus(obj,b)
         c = double(obj) + double(b);
      end
      
      function ind = end(obj,k,n)
         szd = size(obj.Data);
         if k < n
            ind = szd(k);
         else
            ind = prod(szd(k:end));
         end
      end
   end
end

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