Ненавязчивое дублирующее наследование

 

На практике не столь часто встречаются примеры, подобные "межконтинентальным" водителям, в которых нужны и репликация компонентов, и их совместное применение. Они не для новичков. Следует приобрести опыт, чтобы браться за них.

Иначе в попытке использовать дублирующее наследование "в лоб", можно лишь все усложнить, когда это и не нужно.

Рис. 15.19. Избыточное наследование

На рисунке показана типичная ошибка начинающих (или рассеянных разработчиков): класс D объявлен наследником B , ему нужны также свойства класса A , но B сам является потомком A . Забыв о транзитивности наследования, разработчик пишет:

 

class D ... inherit

B

A

...

 

 

В итоге возникает дублируемое наследование. Его избыточность очевидна. Впрочем, при надлежащем соблюдении принятых соглашений все компоненты классов (при сохранении их имен) будут использоваться совместно, новых компонентов не появится, и дополнительных издержек не будет. Даже если в B часть имен атрибутов меняется, единственным следствием этого станет лишь некоторый расход памяти.

Из этого есть только одно исключение: случай, когда B переопределяет один из компонентов A , что приведет к неоднозначности в D . Но тогда, как будет показано ниже, компилятор выдаст сообщение об ошибке, предлагая выбрать в D один из двух вариантов компонента.

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

Такие случаи "безвредного" наследования могут происходить при порождении от универсальных классов ANY и GENERAL , речь о которых пойдет в следующей лекции.