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

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

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

Цель дизайна класса к:

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

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

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

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

  • Данные числовые тестовые данные

  • Описание описание тестовых данных

  • Дата тест даты проводился

Примите, что у вас есть следующие случайные данные (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 должен обработать все типы индексации. Метод subsref:

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

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

  • Задает его собственную версию индексации '()'.

Результат: 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);
            return
         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:

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

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

  • Задает его собственную версию индексации '()'.

Функция 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.

Поскольку плюс метод реализует сложение путем добавления двойных массивов, 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);
                  return
               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

Похожие темы

Была ли эта тема полезной?