Читаем Основы объектно-ориентированного программирования полностью

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)

сопоставляющий элементы списков, если и только если их типы полностью совместимы.

<p>Ключевые концепции</p>

[x]. Статическая типизация - залог надежности, читабельности и эффективности.

[x]. Чтобы быть реалистичной, статической типизации требуется совместное применение механизмов: утверждений, множественного наследования, попытки присваивания, ограниченной и неограниченной универсальности, закрепленных объявлений. Система типов не должна допускать ловушек (приведений типа).

[x]. Практические правила повторного объявления должны допускать ковариантное переопределение. Типы результатов и аргументов при переопределении должны быть совместимыми с исходными.

[x]. Ковариантность, также как и возможность скрытия потомком компонента, экспортированного предком, в сочетании с полиморфизмом порождают редко встречающуюся, но весьма серьезную проблему нарушения типов.

[x]. Этих нарушений можно избежать, используя: глобальный анализ (что непрактично), ограничивая ковариантность закрепленными типами (что противоречит принципу "Открыт-Закрыт"), решение Кэтколл, препятствующее вызову полиморфной целью подпрограммы с ковариантностью или скрытием потомком.

<p>Библиографические замечания</p>

Ряд материалов этой лекции представлен в докладах на форумах OOPSLA 95 и TOOLS PACIFIC 95, а также опубликован в [M 1996a]. Ряд обзорных материалов заимствован из статьи [M 1989e].

Понятие автоматического выведения типов введено в [Milner 1989], где описан алгоритм выведения типов функционального языка ML. Связь между полиморфизмом и проверкой типов была исследована в работе [Cardelli 1984a].

Приемы повышения эффективности кода динамически типизированных языков в контексте языка Self можно найти в [Ungar 1992].

Теоретическую статью, посвященную типам в языках программирования и оказавшую большое влияние на специалистов, написали Лука Карделли (Luca Cardelli) и Петер Вегнер (Peter Wegner) [Cardelli 1985]. Эта работа, построенная на базе лямбда-исчисления (см. [M 1990]), послужила основой многих дальнейших изысканий. Ей предшествовала другая фундаментальная статья Карделли [Cardelli 1984].

Перейти на страницу:

Похожие книги