do
if other /= Void then
Result := 'Новый объект того же типа, что other'
Result.copy (other)
end
ensure
equal (Result, other)
end
Фраза 'Новый объект того же типа, что other' есть неформальное обозначение вызова функции, которая создает и возвращает объект того же типа, что и
Несмотря на замораживание компонента
Переопределять
frozen equal (some, other: ...): BOOLEAN is
-- Обе сущности some и other пусты или присоединены
-- к объектам, которые можно считать равными?
do
Result := ((some = Void) and (other = Void)) or else some.is_equal (other)
ensure
Result = ((some = Void) and (other = Void)) or else some.is_equal (other)
end
Вызов
Не злоупотребляйте замораживанием
Приведенные примеры замораживания - это типичные образцы применения механизма, гарантирующего точное соответствие копий и клонов семантике исходного класса.
Замораживание компонентов не следует делать по соображениям эффективности. (Эту ошибку иногда совершают программисты, работающие на C++ или Smalltalk, которым внушили мысль, будто динамическое связывание накладно и его нужно по возможности избегать.) Хотя вызов замороженных компонентов означает отсутствие динамического связывания, это лишь побочный эффект механизма frozen, а не его конечная цель. Выше мы подробно говорили о том, что безопасное статическое связывание - это проблема оптимизации, и решает ее компилятор, а не программист. В грамотно спроектированном языке компилятор обладает всем необходимым для такой и даже более сильной оптимизации, скажем, для подстановки тела функции в точку вызова (routine inlining). Поиск возможностей оптимизации - задача машин, а не человека. Пользуйтесь frozen в редких, но важных для себя случаях, когда это действительно необходимо (для обеспечения точного соответствия семантике исходной реализации), и пусть ваш язык и ваш компилятор делают свою работу.
Ограниченная универсальность
Расширяя базовое понятие класса, мы представляли наследование и универсальность (genericity) как своего рода 'партнеров'. Объединить их нам позволило знакомство с полиморфными структурами данных: в контейнер - объект, описанный сущностью типа
Вектора, допускающие сложение
Приведем простой, но характерный пример, демонстрирующий необходимость введения ограниченной универсальности. Он поможет в обосновании метода решения поставленной задачи и в выборе соответствующей конструкции языка.
Предположим, что мы хотим объявить класс
indexing
description: 'Векторы со сложением'
class
VECTOR [G]
feature -- Доступ
count: INTEGER
-- Количество элементов
item, infix '@' (i: INTEGER): G is
-- Элемент вектора с индексом i (нумерация с 1)
require ... do
...