Полиморфные структуры данных
Полиморфные структуры данных
Рассмотрим массив многоугольников:
poly_arr: ARRAY [POLYGON]
Когда некоторое значение x присваивается элементу этого массива, как в вызове
poly_arr.put (x, some_index)
(для некоторого допустимого значения индекса some_index), то спецификация класса ARRAY указывает, что тип присваиваемого значения должен быть согласован с типом фактического родового параметра:
class ARRAY [G] creation
...
feature - Изменение элемента
put (v: G; i: INTEGER) is
-- Присвоить v элементу с индексом i
...
end
Так как тип формального аргумента v, соответствующего x, в классе определен как G, а фактический родовой параметр, соответствующий G в вызове poly_arr, - это POLYGON, то тип x должен быть согласован с ним. Как мы видели, для этого x не обязан иметь тип POLYGON, подойдет любой потомок типа POLYGON.
Поэтому, если границы массива равны 1 и 4, то можно объявить некоторые сущности:
p: POLYGON; r: RECTANGLE; s: SQUARE; t: TRIANGLE
и, создав соответствующие объекты, можно выполнить операции
poly_arr.put (p, 1)
poly_arr.put (r, 2)
poly_arr.put (s, 3)
poly_arr.put (t, 4)
которые присвоят элементам массива ссылки на объекты различных типов.
Рис. 14.4. Полиморфный массив
На этом рисунке графические объекты представлены соответствующими геометрическими фигурами, а не обычными диаграммами объектов с набором их полей.Такие структуры данных, содержащие объекты разных типов, имеющих общего предка, называются полиморфными структурами данных. Далее будут рассмотрены многочисленные примеры таких структур. Массивы - это только одна из возможностей, полиморфными могут быть любые структуры контейнеров: списки, стеки и т.п.
Полиморфные структуры данных реализуют цель, сформулированную в начале лекции: объединение порождения и наследования для достижения максимальной гибкости и надежности. Имеет смысл напомнить рис. 10.1, иллюстрирующий эту мысль:
Рис. 14.5. Измерения обобщения
Типы, которые на рис. 10.1 неформально назывались SET_OF_BOOKS и т. п., заменены типами, выведенными из родового универсального типа, - SET [BOOK].
Такая комбинация универсальности и наследования является весьма сильным средством. Оно позволяет описывать структуру объектов с нужной степенью общности. Например,
LIST [RECTANGLE]: может содержать квадраты, но не треугольники.
LIST [POLYGON]: может содержать квадраты, прямоугольники, треугольники, но не круги.
LIST [FIGURE]: может содержать экземпляры любого типа из иерархии FIGURE, но не книги или банковские счета.
LIST [ANY]: может содержать объекты любого типа.
В последнем случае использован класс ANY, который условимся считать предком любого класса (он будет подробнее рассмотрен далее).
Варьируя место класса, выбираемого в качестве фактического родового параметра, в иерархии, можно точно установить границы типов объектов, допустимых в определяемом контейнере.