Основы объектно-ориентированного проектирования


Неограниченная универсальность


Механизм эмуляции неограниченной универсальности остается тем же самым. Этот случай можно рассматривать как специальную форму ограниченной универсальности с пустым множеством ограничений. Как и выше, типы формальных параметров будут рассматриваться как АТД, но без относящихся к ним операций. Эта техника работает, но вряд ли ее стоит применять, поскольку такой пустой тип не соответствует никакой реальности данных.

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

class QUEUABLE end

Мы можем теперь объявить класс QUEUE, чьи операции применимы к объектам QUEUABLE. (Помните, что этот класс не предлагается как образец совершенства хорошего ОО-проектирования, мы по-прежнему добровольно играем с не лучшей версией ОО-нотации, не имеющей универсальности.) Постусловия программы опущены для краткости. И хотя в принципе функция item могла бы служить якорем, ее тело не будет изменяться потомками, так что лучше использовать искусственный якорь во избежание ее переопределения.

indexing description: "Очередь, реализованная массивом" class QUEUE creation make feature -- Initialization make (m: INTEGER) is -- Создание очереди, вмещающей m элементов require m >= 0 do create implementation.make (1, m); capacity := m first := 1; next := 1 end feature -- Access capacity, first, next, count: INTEGER item: like item_anchor is -- Старейший (первый пришедший) элемент очереди require not empty do Result := implementation.item (?rst) end feature -- Status report empty: BOOLEAN is -- Пуста ли очередь? do Result := (count = 0) end full: BOOLEAN is -- Заполнен ли массив? do Result := (count = capacity) end feature -- Element change put (x: like item_anchor) is -- Добавление x в конец очереди require not full do implementation.put (x, next); count := count + 1 next := successor (next) end remove is -- Удаление старейшего элемента require not empty do first := successor (first); count := count - 1 end feature {NONE} -- Implementation item_anchor: QUEUABLE is do end implementation: ARRAY [like item_anchor] successor (n: INTEGER): INTEGER is -- Значение, следующее за n, циклически в интервале 1 ..


Начало  Назад  Вперед



Книжный магазин