Класс с измененной индексацией

Как изменить индексацию классов

Этот пример задает класс, который изменяет поведение индексации по умолчанию путем реализации 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

Реализуйте subsref метод для поддержки индексации по умолчанию и специализированного типа.

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

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

    obj(2,3)
    

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

Для достижения целей проекта subsref метод должен обрабатывать все типы индексации. The 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. Путем реализации double метод конвертера, возможно добавить MyDataClass объект другому классу объекта. Однако другой класс должен реализовать double метод, который также возвращает массив типа double. Для получения дополнительной информации о преобразовании типов см. раздел «Преобразователи объектов».

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

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

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

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

The 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

Похожие темы