В итоге возникает дублируемое наследование. Его избыточность очевидна. Впрочем, при надлежащем соблюдении принятых соглашений все компоненты классов (при сохранении их имен) будут использоваться совместно, новых компонентов не появится, и дополнительных издержек не будет. Даже если в
Из этого есть только одно исключение: случай, когда
Избыточное, хотя и безвредное наследование может произойти, если
| Такие случаи 'безвредного' наследования могут происходить при порождении от универсальных классов |
Правило переименования
В этом разделе мы не введем никаких новых понятий, а лишь точнее сформулируем известные правила и приведем пример, призванный пояснить сказанное.
Начнем с запрета возникновения конфликта имен:
Определение: финальное имя
Финальным именем компонента класса является:
[x]. Для непосредственного компонента (объявленного в самом классе) - имя, под которым он объявлен.
[x]. Для наследуемого компонента без переименования - финальное имя компонента (рекурсивно) в том родительском классе, от которого оно унаследовано.
[x]. Для переименованного компонента - имя, полученное при переименовании.
Правило одного имени
Разные эффективные компоненты одного класса не могут иметь одно и то же финальное имя.
Конфликт имен происходит в том случае, когда два разных по сути компонента, оба эффективные (реализованные), имеют одно финальное имя. Такой конфликт делает класс некорректным, однако ситуацию легко исправить, добавив надлежащее предложение переименования.
Ключевым в тексте правила является слово 'разные'. Если под одним именем мы наследуем от родителей компонентов их общего предка, действует принцип совместного использования компонентов: наследуется один компонент, и конфликта имен не возникает.
Запрет на дублирование имен касается лишь эффективных компонентов. Если один или более компонентов с омонимичными именами являются отложенными, их можно фактически слить воедино, поскольку отсутствует несовместимость реализаций. Подробнее мы поговорим об этом чуть ниже.
Приведенные правила просты и интуитивны. Чтобы в последний раз нам убедиться в их правильном понимании, построим простой пример, демонстрирующий допустимые и недопустимые варианты наследования.
Рис. 15.20. Два варианта наследования
class A feature
this_one_OK: INTEGER
end
class B inherit A feature
portends_trouble: REAL
end
class C inherit A feature
portends_trouble: CHARACTER
end
class D inherit
-- Это неправильный вариант!
B
C
end
Класс
Два компонента
Переименовав один из компонентов, мы с легкостью сделаем
class D inherit
-- Этот вариант класса теперь полностью корректен.
B
rename portends_trouble as does_not_portend_trouble_any_more end
C
end
Конфликт переопределений
Пока в ходе наследования мы меняли лишь имена. А что, если промежуточный предок, такой, как
