Как создать массив объектов абстрактного класса в MATLAB?
В качестве примера предположим, что я создал абстрактный класс под названием Shape
и два подкласса под названием Circle
и Rectangle
, которые реализуют (абстрактный) метод под названием Draw
. Я хотел бы иметь возможность создавать несколько объектов Circle
и Rectangle
, хранить их в массиве и вызывать Draw
для каждого объекта массива путем итерации через массив.
Я пробовал что-то вроде следующего:
Shape.m:
classdef (Abstract) Shape < handle
methods (Abstract)
Draw(obj);
end
end
Circle.m:
classdef Circle < Shape
methods
function obj = Draw(obj)
disp('This is a circle');
end
end
end
Rectangle.m:
classdef Rectangle < Shape
methods
function obj = Draw(obj)
disp('This is a rectangle');
end
end
end
test.m:
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();
Ответы
Ответ 1
Как видно из ошибки, вы не можете создать абстрактный класс (подробнее см. ответ sebastian). Однако есть специальный суперкласс, называемый matlab.mixin.Heterogeneous
, из которого вы можете получить возможность создания массива разных классов.
Сначала выведите matlab.mixin.Heterogeneous
в Shape.m:
classdef (Abstract) Shape < handle & matlab.mixin.Heterogeneous
Затем в вашем тесте script инициализируйте 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
, чтобы указать объект по умолчанию. Это должно быть переопределено для абстрактных базовых классов:
Переопределить этот метод, если Root Class является абстрактным или не является подходящим объектом по умолчанию для классов в гетерогенной иерархии. 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.
Ответ 2
Из документов:
abstract class — A class that cannot be instantiated, but that defines class components used by subclasses.
Смотрите: Mathworks-Docs
Что такое, afaik, определение абстрактных классов на других языках программирования (кто-то поправьте меня, если я ошибаюсь).
Итак, чтобы построить массив, который содержит различные типы элементов 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
ИЗМЕНИТЬ 2:
См. Решение chappjc для этой проблемы;)