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

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

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

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

Рис. 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, речь о которых пойдет в следующей лекции.