exponenta event banner

Поддержка классов для функций создания массивов

Расширение функций создания массивов для вашего класса

Существует несколько функций MATLAB ®, создающих массивы определенного размера и типа, например: ones и zeros. Определяемые пользователем классы могут добавлять поддержку функций создания массивов, не требуя использования перегруженного синтаксиса метода.

Поддержка класса для любой из функций создания массива позволяет разрабатывать код, который можно совместно использовать со встроенными и пользовательскими типами данных. Например, класс переменной x в следующем коде может быть встроенным типом во время начальной разработки, а затем быть заменен определяемым пользователем классом, который прозрачно перегружает zeros:

cls = class(x);
zArray = zeros(m,n,cls);

Функции создания массивов создают массивы определенного типа двумя способами:

  • Синтаксис имени класса - указывает имя класса, определяющее тип элементов массива.

  • Синтаксис объекта Prototype - предоставляет объект Prototype, используемый функцией для определения типа и других характеристик элементов массива.

Например:

zArray = zeros(2,3,'uint8');
p = uint8([1 3 5 ; 2 4 6]);
zArray = zeros(2,3,'like',p);

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

zArray = zeros(2,3,'MyClass');

Или передайте объект вашего класса:

p = MyClass(...);
zArray = zeros(size(p),'like',p);

MATLAB использует эти аргументы для отправки соответствующему методу в классе.

Функции создания массивов, поддерживающие перегрузку

Следующие функции поддерживают этот вид перегрузки.

Функции создания массива
ones
zeros
eye
nan (нижний регистр)
inf
true
false
cast
rand
randn
randi

Какой синтаксис использовать

Чтобы создать массив объектов по умолчанию, которые не требуют входных аргументов для конструктора, используйте синтаксис имени класса.

Чтобы создать массив объектов с определенными значениями свойств или если конструктору требуются другие входные данные, используйте объект prototype для предоставления этой информации.

Классы могут поддерживать как имя класса, так и синтаксис объекта прототипа.

Синтаксис имени класса можно реализовать с помощью true и false хотя эти функции не поддерживают этот синтаксис по умолчанию.

Метод имени класса вызывается, если метод прототипа не существует

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

zeros(...,'like',MyClass(...))

В случае вызова синтаксиса объекта прототипа MATLAB сначала выполняет поиск метода с именем zerosLike. Если MATLAB не может найти этот метод, он вызывает zeros статический метод.

Эта функция полезна, если для создания массива необходимо только имя класса. Нет необходимости реализовывать оба метода для поддержки полного синтаксиса функции создания массива. При реализации только синтаксиса имени класса вызов синтаксиса прототипа объекта совпадает с вызовом синтаксиса имени класса.

Реализация поддержки функций создания массивов

Используйте два отдельных метода для поддержки функции создания массива. Один метод реализует синтаксис имени класса, а другой - синтаксис объекта прототипа.

Например, для поддержки zeros функция:

  • Реализовать синтаксис имени класса:

    zeros(...,'ClassName')

    Как Static способ:

    methods (Static)
       function z = zeros(varargin)
          ...
       end
    end
  • Реализовать синтаксис объекта прототипа:

    zeros(...,'like',obj)

    Как Hidden с помощью char вектор 'Like' добавлено к имени.

    methods (Hidden)
       function z = zerosLike(obj,varargin)
          ...
       end
    end

Как MATLAB интерпретирует вызов функции

Специальная поддержка функций создания массива является результатом интерпретации синтаксиса.

  • Вызов zeros функция этой формы:

    zeros(...,'ClassName')
    

    Вызывает статический метод класса со следующим синтаксисом:

    ClassName.zeros(varargin{1:end-1})
  • Вызов zeros функция этой формы:

    zeros(...,'like',obj)

    Вызывает метод класса со следующим синтаксисом:

    zerosLike(obj,varargin{1:end-2})

Поддержка всех функциональных входов

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

  • Нет входных аргументов измерения, приводящих к возврату скаляра. Например:

    z = zeros('MyClass');
  • Один или несколько размеров равны нулю или меньше нуля, что приводит к появлению пустого массива. Например:

    z = zeros(2,0,'MyClass');
  • Любое количество допустимых размеров массива, указывающих размер массива. Например:

    z = zeros(2,3,5,'MyClass');

Когда функция создания массива вызывает метод класса, она передает входные аргументы, исключая имя класса или литерал 'like' и переменная объекта для метода. Методы можно реализовать с помощью следующих сигнатур:

  • zeros(varargin) для методов «имя класса»

  • zeros(obj,varargin) для методов «like prototype object»

Класс образца

Color класс представляет цвет в определенном цветовом пространстве, например, RGB, HSVи так далее. При обсуждении реализаций метода имени класса и реализации метода прототипа объекта этот класс используется в качестве основы для реализаций перегруженного метода.

classdef Color
   properties
      ColorValues = [0,0,0]
      ColorSpace = 'RGB'
   end
   methods
      function obj = Color(cSpace,values)
         if nargin > 0
            obj.ColorSpace = cSpace;
            obj.ColorValues = values;
         end
      end
   end
end

Реализации метода имени класса

zeros функция снимает окончательный ClassName char и использует его для формирования вызова статического метода в Color класс. Аргументы, передаваемые статическому методу, являются аргументами измерения массива.

Вот реализация zeros метод для Color класс. Эта реализация:

  • Определяет zeros метод как Static (обязательно)

  • Возвращает скаляр Color объект, если вызов zeros не имеет аргументов измерения

  • Возвращает пустой массив, если вызов zeros имеет любые аргументы размерности, равные 0.

  • Возвращает массив по умолчанию Color объекты. Использовать repmat для создания массива размеров, указанных вызовом zeros.

classdef Color
   ...
   methods (Static)
      function z = zeros(varargin)
         if (nargin == 0)
         % For zeros('Color')
            z = Color;
         elseif any([varargin{:}] <= 0)
         % For zeros with any dimension <= 0   
            z = Color.empty(varargin{:});
         else
         % For zeros(m,n,...,'Color')
         % Use property default values
            z = repmat(Color,varargin{:});
         end
      end
   end
end

zeros метод использует значения по умолчанию для ColorValues , поскольку эти значения подходят для данного приложения. Осуществление ones метод может установить ColorValues свойство для [1,1,1], например.

Предположим, что требуется перегрузить randi выполнение следующих задач:

  • Определить каждый ColorValue свойство как массив 1 на 3 в диапазоне от 1 до указанного максимального значения (например, 1-255).

  • Приспосабливайте скалярные, пустые и многомерные размеры массива.

  • Возврат массива Color объекты указанных размеров, каждый со случайными ColorValues.

classdef Color
   ...
   methods (Static)
      function r = randi(varargin)
         if (nargin == 0)
            % For randi('ClassName')
            r = Color('RGB',randi(255,[1,3]));
         elseif any([varargin{2:end}] <= 0)
            % For randi with any dimension <= 0
            r = Color.empty(varargin{2:end});
         else
            % For randi(max,m,n,...,'ClassName')
            if numel([varargin{:}]) < 2
               error('Not enough input arguments')
            end
            dims = [varargin{2:end}];
            r = zeros(dims,'Color');
            for k = 1:prod(dims)
               r(k) = Color('RGB',randi(varargin{1},[1,3]));
            end
         end
      end
   end
end

Реализация метода прототипа объекта

Цель метода, возвращающего массив объектов, «похожих на объект прототипа», зависит от требований класса. Для Color класс, zeroLike создает объекты, имеющие ColorSpace значение свойства объекта прототипа, но ColorValues все равны нулю.

Вот реализация zerosLike метод для Color класс. Эта реализация:

  • Определяет zerosLike метод как Hidden

  • Возвращает скаляр Color объект, если вызов zeros функция не имеет аргументов измерения

  • Возвращает пустой массив, если вызов zeros имеет любые аргументы измерения, отрицательные или равные 0.

  • Возвращает массив Color объектов размеров, указанных вызовом zeros функция.

classdef Color
   ...
   methods (Hidden)
      function z = zerosLike(obj,varargin)
         if nargin == 1
            % For zeros('like',obj)
            cSpace = obj.ColorSpace;
            z = Color;
            z.ColorSpace = cSpace;
         elseif  any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'like',obj)
            if ~isscalar(obj)
               error('Prototype object must be scalar')
            end
            obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues));
            z = repmat(obj,varargin{:});
         end
      end
   end
end

Полный список классов

Вот Color определение класса с перегруженными методами.

Примечание

На практике, Color класс требует проверки ошибок, преобразования цветового пространства и т. д. Эта чрезмерно упрощенная версия иллюстрирует реализацию перегруженных методов.

classdef Color
   properties
      ColorValues = [0,0,0]
      ColorSpace = 'RGB'
   end
   methods
      function obj = Color(cSpace,values)
         if nargin > 0
            obj.ColorSpace = cSpace;
            obj.ColorValues = values;
         end
      end
   end
   methods (Static)
      function z = zeros(varargin)
         if (nargin == 0)
            % For zeros('ClassName')
            z = Color;
         elseif any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'ClassName')
            % Use property default values
            z = repmat(Color,varargin{:});
         end
      end
      function r = randi(varargin)
         if (nargin == 0)
            % For randi('ClassName')
            r = Color('RGB',randi(255,[1,3]));
         elseif any([varargin{2:end}] <= 0)
            % For randi with any dimension <= 0
            r = Color.empty(varargin{2:end});
         else
            % For randi(max,m,n,...,'ClassName')
            if numel([varargin{:}]) < 2
               error('Not enough input arguments')
            end
            dims = [varargin{2:end}];
            r = zeros(dims,'Color');
            for k = 1:prod(dims)
               r(k) = Color('RGB',randi(varargin{1},[1,3]));
            end
         end
      end
   end
   methods (Hidden)
      function z = zerosLike(obj,varargin)
         if nargin == 1
            % For zeros('like',obj)
            cSpace = obj.ColorSpace;
            z = Color;
            z.ColorSpace = cSpace;
         elseif  any([varargin{:}] <= 0)
            % For zeros with any dimension <= 0
            z = Color.empty(varargin{:});
         else
            % For zeros(m,n,...,'like',obj)
            if ~isscalar(obj)
               error('Prototype object must be scalar')
            end
            obj = Color(obj.ColorSpace,zeros(1,3,'like',obj.ColorValues));
            z = repmat(obj,varargin{:});
         end
      end
   end
end

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