Полное соответствие
Полное соответствие
Завершая обсуждение ковариантности, полезно понять, как общий метод можно применить к решению достаточно общей проблемы. Метод появился как результат Кэтколл-теории, но может использоваться в рамках базисного варианта языка без введения новых правил.
Пусть существуют два согласованных списка, где первый задает лыжников, а второй - соседа по комнате для лыжника из первого списка. Мы хотим выполнять соответствующую процедуру размещения share, только если она разрешена правилами описания типов, которые разрешают поселять девушек с девушками, девушек-призеров с девушками-призерами и так далее. Проблемы такого вида встречаются часто.
Возможно простое решение, основанное на предыдущем обсуждении и попытке присваивания. Рассмотрим универсальную функцию fitted (согласовать):
fitted (other: GENERAL): like other is
-- Текущий объект (Current), если его тип соответствует типу объекта,
-- присоединенного к other, иначе void.
do
if other /= Void and then conforms_to (other) then
Result ?= Current
end
end
Функция fitted возвращает текущий объект, но известный как сущность типа, присоединенного к аргументу. Если тип текущего объекта не соответствует типу объекта, присоединенного к аргументу, то возвращается Void. Обратите внимание на роль попытки присваивания. Функция использует компонент conforms_to из класса GENERAL, выясняющий совместимость типов пары объектов.
Замена conforms_to на другой компонент GENERAL с именем same_type дает нам функцию perfect_fitted (полное соответствие), которая возвращает Void, если типы обоих объектов не идентичны.
Функция fitted - дает нам простое решение проблемы соответствия лыжников без нарушения правил описания типов. Так, в код класса SKIER мы можем ввести новую процедуру и использовать ее вместо share, (последнюю можно сделать скрытой процедурой).
safe_share (other: SKIER) is
-- Выбрать, если допустимо, other как соседа по номеру.
-- gender_ascertained - установленный пол
local
gender_ascertained_other: like Current
do
gender_ascertained_other := other .fitted (Current)
if gender_ascertained_other /= Void then
share (gender_ascertained_other)
else
"Вывод: совместное размещение с other невозможно"
end
end
Для other произвольного типа SKIER (а не только like Current) определим версию gender_ascertained_other, имеющую тип, закрепленный за Current. Гарантировать идентичность типов нам поможет функция perfect_ fitted.
При наличии двух параллельных списков лыжников, представляющих планируемое размещение:
occupant1, occupant2: LIST [SKIER]
можно организовать цикл, выполняя на каждом шаге вызов:
occupant1.item.safe_share (occupant2.item)
сопоставляющий элементы списков, если и только если их типы полностью совместимы.