Множественное наследование
Множественное наследование позволяет классу иметь более одного суперкласса, наследуя свойства (атрибуты и операции) всех своих суперклассов. Класс, имеющий несколько суперклассов, называется объединённым классом. Свойства класса-предка, встречающегося более, чем один раз, в графе наследования, наследуются только в одном экземпляре. Конфликты между параллельными определениями порождают двусмысленности, которые должны разрешаться во время реализации. На практике следует избегать таких двусмысленностей или плохого понимания даже в тех случаях, когда конкретный язык программирования, выбранный для реализации системы, предоставляет возможность их разрешения, используя приоритеты или какие-либо другие средства.
Пример множественного наследования приведён на рисунке 2.20, на котором рассмотрена классификация транспортных средств. Класс транспортное средство имеет два подкласса сухопутное ТС и водное ТС (зачернённый треугольник, используемый для обозначения наследования, означает, что подклассы имеют непустое пересечение). Класс амфибии имеет два суперкласса сухопутное ТС и водное ТС, наследуя все свойства (атрибуты и операции) как класса сухопутное ТС, так и класса водное ТС.
Рис. 2.20. Множественное наследование
Ещё один пример множественного наследования приведён на рисунке 2.21, где рассмотрено множественное наследование от непересекающихся классов. В этом случае, который наиболее типичен для применения множественного наследования, свойства, унаследованные от разных предков, дополняют друг друга.
Рис. 2.21. Множественное наследование от непересекающихся классов
В случае если множественное наследование не поддерживается языком программирования, выбранным для реализации, оно может быть заменено одним из следующих способов.
Использование вложенного простого наследования представлено на рисунке 2.22.
Рис. 2.22. Реализация множественного наследования
с помощью вложенного простого наследования
Делегирование с использованием агрегации ролей показано на рисунке 2.23. Делегированием называется механизм реализации, в котором объект, ответственный за операцию, пересылает (делегирует) эту операцию другому объекту; в объектно-ориентированных языках делегирование реализуется путём присоединения методов непосредственно к объектам, а не к классам.
Рис. 2.23. Реализация множественного наследования путём делегирования с использованием агрегации ролей
В рассматриваемом примере операции классов оплата труда и пенсионное обеспечение делегируются объектам класса служащий, который можно рассматривать как результат агрегации классов оплата труда и пенсионное обеспечение. Более подробно делегирование будет рассмотрено в разделе 5.
Ещё один способ использования делегирования для реализации множественного наследования показан на рисунке 2.24. При этом способе суперкласс, наиболее существенный по передаче своих свойств, остаётся единственным суперклассом рассматриваемого подкласса, а свойства остальных суперклассов делегируются объектам этого подкласса.
Рис. 2.24. Реализация множественного наследования
с использованием простого наследования и делегирования
Возможны и другие способы замены множественного наследования. Во всех случаях при выборе способа замены множественного наследования нужно руководствоваться следующими правилами:
если подкласс имеет несколько суперклассов, каждый из которых одинаково существен, лучше всего использовать делегирование (рис. 2.23);
если наиболее существенным является только один из суперклассов, а остальные не так важны, наилучшим способом является реализация множественного наследования через простое наследование и делегирование (рис. 2.24);
если число возможных комбинаций групп наследуемых свойств невелико, можно использовать вложенное простое наследование (рис. 2.22); в случае большого числа комбинаций этот способ применять не следует;
если один из суперклассов передаёт подклассу намного большее число свойств, чем остальные суперклассы, следует сохранить наследование по этому пути (это возможно в ситуациях, представленных на рисунках 2.22 и 2.24);
если решено использовать вложенное простое наследование, то на первый уровень вложенности следует поместить наиболее существенный по передаче свойств суперкласс, затем наиболее существенный из оставшихся суперклассов и т.д. (рис. 2.22);
следует избегать использования вложенного простого наследования (рис. 2.22), если это ведёт к дублированию достаточно больших частей программы;
следует помнить, что только вложенное простое наследование (рис. 2.22) обеспечивает полную тождественность множественному наследованию.