Программирование >>  Хронологические базы данных 

1 ... 238 239 240 [ 241 ] 242 243 244 ... 348


ди данной окружности приводило к одному и тому же результату независимо от того, рассматривается эта окружность именно как окружность или же как эллипс. Другими словами, предположим, что перечисленные ниже события происходят в указанной последовательности.

1. Определяются тип ELLIPSE и соответствующая версия оператора AREA. Предположим для простоты, что код оператора AREA не предусматривает использование реального представления для эллипсов.

2. Определяется тип CIRCLE как подтип типа ELLIPSE, но пока не определяется отдельная версия реализации оператора AREA для окружностей.

3. Вызывается оператор AREA для некоторой конкретной окружности с, чтобы получить результат, помещаемый, например, в переменную areal. Этот вызов использует, естественно, версию оператора AREA для типа ELLIPSE.

4. Определяется собственная версия реализации оператора AREA для окружностей.

5. Вновь вызывается оператор AREA для той же окружности с, чтобы получить результат, помещаемый, например, в переменную агеа2 (и на этот раз уже используется версия оператора AREA для типа CIRCLE).

Нам бы хотелось, конечно, настаивать на том, что условие areal=area2 должно выполняться. Но это возможное требование ничем не обеспечено, поскольку, как уже отмечалось, всегда существует вероятность того, что версия оператора AREA, реализованная для окружностей, может возвращать, например, длину окружности вместо площади или просто неверное значение площади круга.

Теперь возвратимся к примеру с оператором TRAVEL TIME. На самом деле мы считаем этот пример, как и другие подобные ему, крайне неубедительным, т.е. никак не убеждающим нас в том, что в указанных ситуациях может быть желательным изменение семантики оператора. Рассмотрим возможные последствия.

Если тип TOLL HIGHWAY является настоящим подтипом типа HIGHWAY, это по определению означает, что каждая отдельная платная дорога является фактически дорогой.

Следовательно, некоторые дороги (т.е. некоторые значения типа HIGHWAY) являются действительно платными дорогами и имеют кассы для оплаты проезда. Тогда тип HIGHWAY - это не дороги без касс для оплаты проезда , а дороги с п кассами для оплаты проезда (где п может быть равно нулю).

Поэтому оператор TRAVEL TIME для типа HIGHWAY не вычисляет время проезда по дорогам, на которых нет касс , а вычисляет время проезда d/s по некоторым дорогам, игнорируя кассы для оплаты проезда .

Оператор TRAVEL TIME для типа TOLL HIGHWAY, напротив, вычисляет время проезда (d/s) + (n*t) по некоторым дорогам, не игнорируя кассы для оплаты проезда . Таким образом, эти два оператора TRAVEL TIME - логически разные операторы. Путаница между двумя различными операторами возникает из-за того, что им присвоили одно и то же имя. Фактически здесь мы имеем дело с перегружаемым, а не с включаемым полиморфизмом.



(В качестве дополнительного замечания отметим, что на практике недоразумения возникают из-за того, что, как это ни печально, многие авторы используют термин перегружаемый полиморфизм для включаемого полиморфизма.)

Подведем итоги. Мы по-прежнему не считаем изменение семантики оператора хорошей идеей. Как мы убедились, данное требование не гарантируется, однако, безусловно, можно определить нашу модель наследования таким образом (что мы и делаем), чтобы утверждать, что если семантика изменилась, то реализация нарушена, т.е. данная реализация не является реализацией модели и последствия непредсказуемы. Обратите внимание, что наша точка зрения на этот вопрос (т.е. то, что мы считаем недопустимыми такие изменения) имеет еще одно преимущество: независимо от того, определены ли какие-либо явные специализации данного оператора, представление пользователя остается одним и тем же. Иначе говоря, существует оператор {отдельный оператор), называемый Ор; он применим ко всем значениям аргументов некоторого конкретного типа Т и, следовательно, по определению - к значениям аргумента любого собственного подтипа типа Т.

19.8. Является ли окружность эллипсом

До сих пор в этой главе подразумевалось, причем довольно обоснованно, что окружности являются эллипсами. Однако необходимо обратить ваше внимание, что в литературе ведутся горячие споры по этому тривиальному вопросу. Рассмотрим наши обычные переменные Е и С, имеющие объявленные типы ELLIPSE и CIRCLE соответственно. Предположим, что эти переменные инициализированы следующим образом.

.Е := ELLIPSE ( LENGTH ( 5.0 ), LENGTH ( 3.0 ),

POINT ( 0.0, 0.0 )) ; С := CIRCLE ( LENGTH ( 5.0 ), POINT ( 0.0, 0.0 )) ;

Обратите внимание, что оба оператора, ТНЕ А(С) и ТНЕ В(С), в данном случае имеют значение 5.

Теперь можно выполнить операцию с переменной Е, например обновить значение длины полуоси а .

ТНЕ А ( Е ) := LENGTH ( 6.0 ) ;

А что будет, если попытаться выполнить аналогичную операцию с переменной С? ТНЕ А ( С ) := LENGTH ( 6.0 ) ;

Мы получим ошибку! Что же это за ошибка? Если бы обновление все-таки произошло, то переменной С предстояло бы содержать окружность , которая нарушает ограничение для окружностей, согласно которому а = b (значение а было бы равно б, а значение Ь, наверное, оставалось бы равным 5, поскольку мы его не изменяли). Иными словами, переменная С содержала бы некруглую окружность и, таким образом, было бы нарушено ограничение для типа CIRCLE.

Поскольку некруглые окружности противоречат логике и здравому смыслу, наверное, разумно предложить, чтобы такое обновление было недопустимо. Также очевидно, что достичь этого можно во время компиляции, отбрасывая все подобные операции. Для этого достаточно определить задаваемую оператором присвоения операцию обновления так, чтобы отдельное обращение к полуосям а и b для окружностей было синтаксически



недопустимо. Иначе говоря, операторы присвоения ТНЕ А и ТНЕ В должны быть неприменимы для типа CIRCLE, а попытка подобного обновления должна приводить к ошибке несовпадения типа во время компиляции.

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

С := CIRCLE (...);

Но вызов оператора выбора для типа CIRCLE в правой части оператора присвоения должен был бы включать как аргумент типа ТНЕ А с новой длиной полуоси а, равной LENGTH(6,0). Однако оператор выбора для типа CIRCLE не принимает аргумента типа ТНЕ А- он принимает аргументы типов THE R и THE CTR. Таким образом, становится ясно, что исходное присвоение должно быть недопустимым!

Об изменении семантики

Учитывая сказанное выше, сразу же отбросим предложение, суть которого заключается в попытке реанимировать идею, состоящую в том, что операторы присвоения ТНЕ А и ТНЕ В должны быть допустимы для окружностей. Обычно предлагается, чтобы, например, оператор ТНЕ А был переопределен, иначе говоря, явно специализирован, для окружностей таким образом, чтобы иметь также побочный эффект присвоения соответствующего значения для оператора ТНЕ В, так что после обновления окружность по-прежнему будет удовлетворять ограничению а = Ь. Мы отвергаем это пpezлoжeниe по крайней мере по следующим трем причинам.

Во-первых, семантика присвоения для операторов ТНЕ А и ТНЕ В предписана нашей моделью наследования и не должна изменяться предлагаемым способом.

Во-вторых, даже если бы эта семантика присвоения не была предписана нашей моделью, мы уже доказали, что изменение семантики оператора произвольным образом - это, вообще говоря, не лучшая идея, а изменение семантики оператора таким способом, который приводит к побочным эффектам- это еще худшая идея. Лучше придерживаться общего принципа, который гласит, что операторы должны делать то, что от них требуется, не больше и не меньше.

И, в-третьих, что наиболее важно, изменение семантики предлагаемым способом не всегда возможно. Например, пусть тип ELLIPSE имеет другой непосредственный подтип NONCIRCLE, и пусть ограничение а > b применимо для подобных неокружностей . Рассмотрим оператор присвоения ТНЕ А для неокружности , который устанавливал бы длину полуоси а равной Ь. Какое тогда должно быть соответствующее семантическое переопределение для этого присвоения? Какой именно побочный эффект был бы подходящим в этом случае?

Существует ли гибкая модель

Итак, мы остались на позициях, когда операторы присвоения ТНЕ А и ТНЕ В применимы для эллипсов вообще, но не применимы для окружностей в частности. Однако дополнительно необходимо учесть следующее.



1 ... 238 239 240 [ 241 ] 242 243 244 ... 348

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика