Я также предпочитаю отображать названия стереотипов на таких диаграммах, поскольку треугольник, изображающий наследование, может закрыть название класса при использовании значков.
После создания суперкласса атрибуты, операции и отношения размещают по возможности на самом высоком уровне иерархии. Какие же свойства необходимо перенести? Давайте посмотрим на иерархию с базовым классом пользователь. Атрибуты, операции и отношения для подклассов показаны на рис. 8.3. Так как атрибуты имя (name) и номер (IDNumber) одинакового формата, их можно с уверенностью перенести в суперкласс пользователь (RegistrationUser). Оба класса связаны с классом учебный курс (CourseOffering). Для этого отношения существуют два варианта:
сохранить отношения на уровне подклассов;
сделать отношение на уровне суперкласса со значением мощности, учитывающим объекты преподаватель и студент (один объект учебный курс связан с объектами пользователь в количестве от 4 до 11). Кроме того, здесь накладывается дополнительное ограничение: один из объектов пользователь должен быть преподавателем.
Какой из этих вариантов является правильным? Оба. Какой из них лучше использовать? Зависит от ситуации. Если требуется, чтобы объект учебный курс «знал» всех студентов и преподавателя, то хранить единый список с такой информацией наверняка будет удобнее. В этом случае воспользуйтесь вторым вариантом. С другой стороны, если нужно знать только студентов или только преподавателей, подойдет первый вариант. Все зависит от требований к системе. В подобных ситуациях следует тщательно изучить функции и сценарии, чтобы определить нужное поведение.
Для перемещения атрибутов и операций в программе Rational Rose:
1. В окне браузера щелкните по значку «+» слева от имени подкласса, чтобы раскрыть список его свойств.
2. Выберите атрибут или операцию, которую нужно переместить.
3. Перетащите с помощью мыши атрибут или операцию на суперкласс.
4. Удалите данный атрибут или операцию из других подклассов.
5. Таким же образом переместите другие необходимые атрибуты из подклассов в суперкласс.
Иерархия наследования после переноса атрибутов показана на рис. 8.4.
Одиночное и множественное наследование
При одиночном наследовании класс содержит единственный набор потомков, то есть одну цепочку суперклассов (например, легковая машина — это автомобиль, а автомобиль — средство передвижения). Множественное наследование включает более одной цепочки суперклассов (машина-амфибия — это автомобиль, автомобиль — средство передвижения, в то же время машина-амфибия — это лодка, а лодка — средство передвижения). При множественном наследовании возникает ряд проблем, в частности конфликт имен и несколько копий унаследованных свойств. Способ решения таких проблем выбирается в зависимости от языка программирования: виртуальные базовые классы в C++ или отсутствие поддержки множественного наследования в PowerBuilder. Множественное наследование может стать причиной запутанного и трудно сопровождаемого кода — чем больше суперклассов, тем труднее определить, что откуда взялось и что произойдет при внесении изменений. Вывод: используйте множественное наследование только при необходимости и с большой осторожностью.
Наследование и агрегация
Наследование часто используется не по назначению. Существует мнение, что «чем больше я буду его использовать, тем лучше станет мой код». Это заблуждение. В действительности неправильное применение наследования может привести к проблемам. Например, студент может учиться очно или заочно. Создадим суперкласс студент (Student) и два подкласса — студент очного отделения (FulltimeStudent) и студент заочного отделения (ParttimeStudent). Во время работы такой структуры наверняка возникнут определенные проблемы. Что случится, если:
студент очного отделения решит перейти на заочное? Это значит, что объекту придется сменить класс;
будет добавлена еще одна размерность (например, студент, получающий стипендию и не получающий стипендию)? Здесь понадобятся новые подклассы для представления информации о стипендии, а также множественное наследование для поддержки всех комбинаций (студент очного отделения, получающий стипендию, студент заочного отделения, получающий стипендию и т. д.).
Наследование должно служить для отделения общности от специфики. Агрегация — для отражения комбинированных отношений. Часто оба типа отношений используются вместе. Класс студент имеет классификацию (агрегацию), которая, в свою очередь, делится на классы студент-очник и студент-заочник (наследование) — см. рис. 8.5.
Резюме