- •9. Проектирование классов
- •9.1. Проектирование классов, скрывающих информацию
- •9.2. Проектирование операций классов
- •9.3. Классы абстрагирования данных
- •9.4. Классы интерфейса устройства
- •9.5. Классы, зависящие от состояния
- •9.6. Классы, скрывающие алгоритмы
- •9.7. Классы интерфейса пользователя
- •9.8. Классы бизнес-логики
- •9.9. Классы-обертки базы данных
- •9.10. Внутренние программные классы
- •9.11. Применение наследования при проектировании
- •9.12. Примеры наследования
- •9.13. Спецификация интерфейса класса
9.10. Внутренние программные классы
Внутренние программные классы скрывают решения разработчика, которые могут со временем измениться. Обычно они создаются на поздних стадиях процесса проектирования. Определить их из аналитической модели, относящейся к предметной области, невозможно.
Внутренние программные классы инкапсулируют различные структуры данных (стеки, очереди, таблицы данных), выбранные проектировщиком. Примерами внутренних классов являются также классы-разъемы.
9.11. Применение наследования при проектировании
Наследование полезно при проектировании двух похожих классов, то есть таких, у которых много общих черт. На этапе проектирования архитектуры его нужно иметь в виду, чтобы впоследствии на этапах детального проектирования и кодирования можно было повторно использовать тот же или слегка видоизмененный код. Наследование задействуют и с целью сделать проект более удобным для сопровождения – такое применение оченъ упрощает инкрементную модификацию программы.
9.11.1. Иерархии классов. Иерархии классов (называемые также иерархиями обобщения/специализации или иерархиями наследования) допустимо разрабатывать сверху вниз, снизу вверх или в обоих направлениях. При разработке сверху вниз проектируется класс, который включает характеристики, общие для всех его наследников. В ходе специализации этого класса формируются подклассы со специфическими особенностями. Можно поступать и наоборот, если в первоначальном проекте есть классы, имеющие как общие черты (операции или атрибуты), так и некоторые отличия. В таком случае общие свойства переносятся в суперкласс и наследуются подклассами.
Следует отметить, что при использовании наследования внутреннее устройство родительских классов видимо подклассам, такой вид повторного применения называется прозрачным ящиком, нарушающим концепцию инкапсуляции (сокрытия-информации). Реализация класса-потомка тесно связана с реализацией родительского класса, что бывает причиной затруднений в глубоких иерархиях наследования. Изменение класса, расположенного на верхнем уровне иерархии, может затронуть всех его потомков. По этой причине стоит ограничить глубину иерархии классов.
9.11.2. Абстрактные классы. У абстрактного класса не может быть экземпляров, поэтому он используется как шаблон для создания классов, а не объектов. Иными словами, он способен выступать только в роли суперкласса, который определяет общий интерфейс для всех своих подклассов. Абстрактная операция – это операция, которая объявлена, но не реализована в абстрактном классе. Абстрактный класс должен иметь хотя бы одну абстрактную операцию.
Абстрактный класс оставляет реализацию некоторых операций своим подклассам. Подкласс в состоянии реализовывать операции, придерживаясь интерфейса, заданного своим абстрактным родителем. Различные подклассы абстрактного класса могут определять разные реализации одной и той же операции. Таким образом, абстрактный класс задает интерфейс в форме набора абстрактных операций. Подклассы реализуют этот интерфейс и расширяют его, добавляя собственные операции.
Некоторые операции разрешается осуществлять в самом абстрактном классе, особенно тогда, когда их реализация в некоторых или всех подклассах должна быть одинаковой. Иногда абстрактный класс определяет реализацию операции по умолчанию. В подклассе эту операцию можно при необходимости заместить. Так делают, когда некий подкласс должен обрабатывать особый случай, для которого реализация по умолчанию не годится.
9.11.3. Полиморфизм и динамическое связывание. Слово «полиморфизм» в переводе с греческого означает «многообразие форм». В объектно-ориентированном проектировании полиморфизм используется, когда в различных классах должна существовать операция с одним и тем же именем. Ее спецификация во всех классах одинакова, но реализация может быть различной: это дает возможность во время выполнения использовать вместо одного объекта другой с тем же интерфейсом.
Динамическое связывание применяется совместно с полиморфизмом для ассоциирования запроса с объектом и одной из его операций во время исполнения. При статическом связывании (типичный случай в процедурных языках) ассоциация запроса с операцией устанавливается во время компиляции, ее нельзя впоследствии изменить. При динамическом связывании, напротив, запрос может сначала выполняться операцией одного объекта, а потом операцией другого объекта.