финальное имя (добавив, если надо, выражение rename). В результате конфликта имен не возникнет (случай (2)), а объединение двух вариантов даст новый компонент.
Конфликты при репликации: выделение
Рассмотрим теперь случай конфликтов переопределений, связанных с репликацией. Пусть при дублируемом наследовании происходит переопределение и переименование эффективного компонента, так что имеем два эффективных компонента, наделенных собственными именами.
Рис. 15.23. Необходимость выделения
Представленный на рисунке класс
Поскольку компоненты наследуются под разными именами, то происходит их репликация. Класс
В отличие от случая совместного использования не возникает конфликта имен. Однако возникают другие конфликты, относящиеся к динамическому связыванию. Пусть полиморфная сущность
Правило динамического связывания гласит: вызываемый вариант
Как и при конфликте имен, нельзя позволять компилятору делать выбор, пользуясь собственными правилами, - это противоречило бы принципам ясности и надежности. Управление ситуацией должно оставаться за автором разработки.
Для устранения неоднозначности необходим простой языковой механизм - предложение select. Вот версия класса, в которой предпочтение при динамическом связывании сущности
class D inherit
B
C
select f end
feature
...
end
В этом варианте предпочтение отдается версии класса
class D inherit
B
select bf end
C
feature
...
end
Синтаксически предложение select следует за предложениями rename, undefine и redefine, если таковые имеются (выбор осуществляется после переименования и переопределения). Применение этого механизма регламентирует следующее правило:
Правило выделения
Класс, наследовавший две или более различные и эффективные версии компонента дублируемого предка и не переопределивший их, должен включить одну из них в предложение select.
Механизм select устраняет неоднозначность раз и навсегда. Потомкам класса нет необходимости (и они не должны) повторять выделение.
Выделение всех компонентов
Любой конфликт переопределений должен быть разрешен посредством select. Если, объединяя два класса, вы натолкнулись на ряд конфликтов, возможно, вы захотите, чтобы один из классов 'одержал верх' (почти) в каждом из них. В частности, так происходит в ситуации, метафорично названной 'брак по расчету' (вспомните,
Решение задачи упрощает следующая запись, дающая возможность не перечислять все конфликтующие компоненты. Предложение inherit класса может содержать такое описание (не более одного) родителя:
SOME_PARENT
select all end
Результат очевиден: все конфликты переопределений, - точнее те из них, что останутся после обработки других select, - разрешатся в пользу
