Как мне создать массив объектов абстрактного класса в MATLAB?

В качестве примера предположим, что я создал абстрактный класс с именем Shape и два подкласса с именами Circle и Rectangle, которые оба реализуют (абстрактный) метод с именем Draw. Я хотел бы иметь возможность создавать несколько объектов Circle и Rectangle, хранить их в массиве и вызывать Draw для каждого объекта массива, перебирая массив.

Я пробовал что-то вроде следующего:

Форма.м:

classdef (Abstract) Shape < handle

    methods (Abstract)
        Draw(obj);
    end

end

Круг.м:

classdef Circle < Shape

    methods
        function obj = Draw(obj)
            disp('This is a circle');
        end
    end

end

Прямоугольник.м:

classdef Rectangle < Shape

    methods
        function obj = Draw(obj)
            disp('This is a rectangle');
        end
    end

end

тест.м:

shapes = Shape.empty();

myrect = Rectangle();
mycirc = Circle();

shapes(end + 1) = myrect;
shapes(end + 1) = mycirc;

for i = 1:size(shapes,1)
    shapes(i).Draw();
end

Когда я пытаюсь запустить test.m, я получаю следующее сообщение об ошибке:

Error using Shape.empty
Abstract classes cannot be instantiated.
Class 'Shape' defines abstract methods
and/or properties.

Error in test (line 1)
shapes = Shape.empty();

person user2978125    schedule 11.11.2013    source источник


Ответы (2)


Как видно из ошибки, вы не можете создать экземпляр абстрактного класса (подробности см. в ответе Себастьяна). Однако существует специальный суперкласс с именем matlab.mixin.Heterogeneous, из которого вы можете вывести, чтобы разрешить создание массива разных классов.

Во-первых, наследуем от matlab.mixin.Heterogeneous в Shape.m:

classdef (Abstract) Shape < handle & matlab.mixin.Heterogeneous

Затем в тестовом сценарии инициализируйте shapes из Circle или Rectangle:

shapes = Circle.empty();

Когда вы запустите цикл, массив изменит класс:

>> shapes

shapes = 

  1x2 heterogeneous Shape (Rectangle, Circle) array with no properties.

>> shapes(1)

ans = 

  Rectangle with no properties.

>> shapes(2)

ans = 

  Circle with no properties.

Это все, что вам нужно, но для дополнительного контроля над гетерогенным массивом вы можете переопределить метод getDefaultScalarElement объекта matlab.mixin.Heterogeneous для указания объекта по умолчанию. Это должно быть переопределено для абстрактных базовых классов:

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

Скажем, вы хотите, чтобы объект по умолчанию был Circle для массива объектов, производных от Shape:

methods (Static, Sealed, Access = protected)
    function default_object = getDefaultScalarElement
        default_object = Circle;
    end
end

Теперь недостающие элементы в массиве объектов, производных от Shape, будут заполнены Circle объектами:

>> clear r
>> r(2) = Rectangle
r = 
  1x2 heterogeneous Shape (Circle, Rectangle) array with no properties.
>> r(1)
ans = 
  Circle with no properties.
>> r(2)
ans = 
  Rectangle with no properties.
person chappjc    schedule 11.11.2013

Из документов:

abstract class — A class that cannot be instantiated, but that defines class components used by subclasses.

См.: Mathworks-Docs

Что, на самом деле, является определением абстрактных классов и в других языках программирования (кто-то поправит меня, если я ошибаюсь).

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

EDIT: Для полноты:

Я попробовал то, что вы пытаетесь достичь, и на первый взгляд массивы объектов со смешанными элементами, которые имеют общий суперкласс, не существуют:

>> objects(1) = Foo();
>> objects(2) = FooBar();
The following error occurred converting from FooBar to Foo:
Error using Foo
Too many input arguments.

>> FooBar

ans = 

  FooBar handle with no properties.
  Methods, Events, Superclasses


Superclasses for class FooBar:

    Foo
    handle

EDIT 2: См. решение этой проблемы от chappjc ;)

person sebastian    schedule 11.11.2013