Конструкторы разнородного массива

Создание массивов в конструкторах суперкласса

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

Когда ошибки могут произойти

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

  • Создание объектных массивов в конструкторах подкласса

  • Вызов конструкторов суперкласса из конструкторов подкласса, чтобы передать аргументы

  • Создание объектных массивов в конструкторе суперкласса

Кроме того, любое из следующего верно:

  • Корневой суперкласс не абстрактен и не реализует метод getDefaultScalarElement.

  • Корневой суперкласс реализует метод getDefaultScalarElement, который возвращает объект, который не является тем же классом как подкласс.

При присвоении объектным массивам MATLAB® использует объект по умолчанию заполнить неприсвоенные элементы массива. В неоднородной иерархии объект по умолчанию может быть суперклассом, который вызван конструктором подкласса. Поэтому создание массива в конструкторе суперкласса может создать разнородный массив.

Если конструктор суперкласса возвращает разнородный массив в конструктора подкласса, MATLAB генерирует ошибку (см. Потенциальную Ошибку).

Инициализация массива в конструкторе суперкласса

Чтобы избежать ошибок, инициализируйте объектный массив явным образом в конструкторе суперкласса. Например, используйте repelem в конструкторе суперкласса, чтобы инициализировать массив прежде, чем инициализировать часть суперкласса объектов. Инициализация массива гарантирует, что все элементы, присвоенные в массив, имеют тот же класс в качестве аргумента obj.

В этом коде конструктор суперкласса создает один объект для каждого элемента во входном параметре, arg:

method
   function obj = SuperClass(arg)
      ...
   n = numel(arg);
   obj = repelem(obj,1,n);
   for k = 1:n
      obj(k).SuperProp = arg(k);
   end
      ...
   end
end

Конструктор подкласса вызывает конструктора суперкласса, чтобы передать массив обязательного аргумента, a:

method
   function obj = SubClass(a)
         obj = obj@SuperClass(a);
         for k = 1:numel(a)
            obj(k).SubProp = a(k);
      end
   end
end

Демонстрационная реализация

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

Эта иерархия классов представляет членов команды инженеров. Классы в иерархии включают:

  • TeamMembers — Суперкласс для определенных классов члена команды, как ProjectEngineer. TeamMembers задает свойства Name и PhoneX и выводит от matlab.mixin.Heterogeneous.

  • ProjectEngineer — Члены команды, которые являются инженерами. Каждый экземпляр наследовал свойство Name и PhoneX и задает тарификационное свойство Rate.

  • Другие участники — Другие типы членов команды, не реализованных для этого примера для простоты.

Класс TeamMembers является корнем неоднородной иерархии и является реальным классом. Прежде, чем присвоить значения свойствам Name и PhoneX, конструктор инициализирует массив подкласса (ProjectEngineer) объекты.

Конструктор ProjectEngineer обеспечивает аргумент obj для вызова repelem с этим оператором:

obj = obj@TeamMembers(varargin{1:2});

Вот класс TeamMembers:

classdef TeamMembers < matlab.mixin.Heterogeneous
   properties
      Name
      PhoneX
   end
   methods
      function obj = TeamMembers(nme,ext)
         if nargin > 0
            n = numel(nme);
            obj = repelem(obj,1,n);
            for k = 1:n
               obj(k).Name = nme{k};
               obj(k).PhoneX = ext(k);
            end
         else
            obj.Name = '';
         end
      end
   end
end

Класс ProjectEngineer представляет один тип члена команды. Этот класс поддерживает входные параметры массивов и возвращает массив объектов.

classdef ProjectEngineer < TeamMembers
   % Inputs: {Name}, [PhoneX], {Rate}
   properties
      Rate
   end
   methods
      function obj = ProjectEngineer(varargin)
         obj = obj@TeamMembers(varargin{1:2});
         for k = 1:numel(varargin{1})
            obj(k).Rate = varargin{3}{k};
         end
      end
   end
end

Класс ProjectEngineer требует массива ячеек имен, числового массива телефонных расширений и массива ячеек расценок для каждого инженера в команде.

nm = {'Fred','Nancy','Claudette'};
px = [8112,8113,8114];
rt = {'C2','B1','A2'};
tm = ProjectEngineer(nm,px,rt)
tm = 

  1x3 ProjectEngineer array with properties:

    Rate
    Name
    PhoneX

Потенциальная ошибка

Конструктор TeamMembers инициализирует объектный массив с этим оператором:

obj = repelem(obj,1,n);

Поскольку аргумент obj к repelem является объектом ProjectEngineer, возвращенный массив имеет тот же класс.

Без этого оператора конструктор TeamMembers создал бы объекты по умолчанию заполнить элементы массива в цикле for. Получившийся разнородный массив имел бы класс общего суперкласса (TeamMembers в этом случае). Если суперкласс возвращает этот разнородный массив в конструктора подкласса, это - нарушение правила, что конструкторы класса должны сохранить класс возвращенного объекта.

MATLAB выпускает эту ошибку:

When constructing an instance of class 'ProjectEngineer', the constructor must
preserve the class of the returned object.

Error in ProjectEngineer (line 8)
         obj = obj@TeamMembers(varargin{1:2});

Похожие темы

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