OpenU.Ru
Абстрактным может быть класс, вариант
использования, сигнал, другой классификатор
или элемент, который допускает обобщения
и экземпляры которого нельзя создать непосредственно.
Абстрактной может быть операция, у которой нет прямой
реализации в программном коде.
Антоним: concrete.
См. abstract operation; generalizable
element.
Семантика
Абстрактный класс - это класс, у которого нет непосредственных экземпляров,
поскольку он имеет неполное описание (отсутствует метод
для одной или нескольких операций) или, если описание класса является полным,
явно указано отсутствие существования экземпляров. Абстрактный класс нуждается
в уточнении. Иными словами, для того, чтобы им можно было пользоваться, у него
должны быть потомки, имеющие реальные экземпляры. Абстрактный класс, являющийся
листом, совершенно бесполезен (хотя он может присутствовать в каркасе, где подлежит
уточнению при использовании каркаса). У конкретного класса не может быть абстрактных
операций (иначе он был бы абстрактным). Абстрактный класс, напротив, вполне
может иметь конкретные операции. Конкретными называются операции, которые могут
быть реализованы в программном коде класса, затем использоваться во всех подклассах.
В процессе реализации конкретных операций используются только атрибуты и операции,
объявленные в данном классе. Одна из целей наследования
- выделить такие операции в абстрактные суперклассы, после чего их могут наследовать
все подклассы. Конкретные операции могут быть полиморфными (их будут переопределять
методы классов-потомков), но это не обязательно. Класс, у которого реализованы
все операции, может быть и абстрактным, однако при этом его абстрактность должна
быть явно декларирована. Класс, у которого не реализована одна или более операций,
автоматически считается абстрактным.
Такая же семантика абстрактности применима и к вариантам использования. Абстрактный
вариант использования представляет собой фрагмент поведения, которое не может
осуществиться само по себе, а должно быть более ясно определено в конкретных
вариантах использования с помощью отношений обобщения, включения, или расширения.
Когда общее поведение выделяется в абстрактный вариант использования, модель
легче понять, потому что она становится меньше и проще.
Подобным образом дело обстоит и с другими абстрактными классификаторами и прочими
элементами модели, допускающими обобщения.
Нотация
Имя абстрактного класса или абстрактной операции пишется курсивом. Кроме того,
вы можете обозначить абстрактность элемента, поместив ключевое слово abstract
в список свойств (под именем элемента или после него).
Например, Account {abstract}.
См. class name.
Пример
На рис. 1 изображен абстрактный класс Account, у которого есть одна абстрактная операция (computeInterest) и одна конкретная (de-jusit). Абстрактный класс имеет два конкретных подкласса, которые реализуют операцию computeInterest. Атрибуты класса всегда конкретные.
Обсуждение
Разница между абстрактным и конкретным классом не так фундаментальна и четка,
как может показаться на первый взгляд. Все зависит от конкретного разработчика
модели. К тому же в процессе проектирования статус класса может меняться. Конкретный
класс может стать абстрактным, если будет принято решение о разделении его возможностей
и ответственностей по отдельным подклассам. Абстрактный класс станет конкретным,
если его подклассы будут сочтены ненужными и убраны из модели или если вместо
подклассов будут использованы значения атрибутов.
Самый простой способ сделать правильный выбор - придерживаться следующего правила:
все нелистовые (non-leaf) классы считать абстрактными, а все листовые классы,
соответственно, конкретными (исключение составляют абстрактные листовые классы,
ожидающие дальнейшего уточнения). Это правило не относится непосредственно к
языку UML, это стиль моделирования, который вы можете принимать или не принимать.
Правило "абстрактного суперкласса" основывается на том, что метод,
реализующий операции в суперклассе, и метод, реализующий операции в конкретном
классе, часто настолько разнятся, что могут не уместиться в рамках одного метода.
В этом случае метод суперкласса вынужден делать следующее: во-первых, реализовать
общее поведение, которое будут наследовать все классы-потомки; во-вторых, реализовать
поведение для специфического класса. Часто эти две цели конфликтуют между собой.
Вместо этого любой неабстрактный суперкласс может быть преобразован в абстрактный
суперкласс и конкретный подкласс. В таком случае абстрактный класс будет содержать
в себе методы, наследуемые всеми подклассами, а конкретный подкласс - методы
для специфического класса, допускающего наличие прямых экземпляров. Правило
"абстрактного суперкласса" позволяет четко определять, какой тип данных
может содержать переменная или параметр: экземпляры конкретного листового класса
или экземпляры любого из подклассов суперкласса.
На рис. 2 изображен класс Letter (Письмо), который смоделировали вопреки правилу
"абстрактного суперкласса". У класса Letter есть операция getNextSentence,
которая возвращает текст следующего непрочитанного предложения, а также операция
resetCursor, которая устанавливает курсор в начале текста. Подкласс Encrypted
Letter (Шифрованное письмо) представляет собой письмо, которое было зашифровано.
Операция getNextSentence в этом случае переопределяется, так как вначале требуется
расшифровка текста. Реализация этой операции будет совершенно иной. Поскольку
Letter - конкретный суперкласс, невозможно отличить переменную, которая должна
содержать только экземпляры класса Letter (в котором операция getNextSentence
не может быть переопределена) от переменной, которая может содержать как Letter,
так и Encrypted Letter.
Изменив модель по правилу "абстрактного суперкласса", мы сделали ее
симметричной (рис. 3). Теперь в ней есть абстрактный суперкласс Letter (которое
может быть как обычным, так и зашифрованным). Кроме этого, появился новый класс
- NonEncryptedLetter(Не-шифрованное письмо). Теперь getNextSentence является
абстрактной операцией, которая реализуется каждым подклассом, a resetCursor
- конкретной операцией, одинаковой для всех подклассов.
Если вы будете строить модель с учетом правила "абстрактного суперкласса",
то можно не объявлять его абстрактным каждый раз, а делать это автоматически
на основе классовой иерархии.
Как мы уже говорили, абстрактный листовой класс бесполезен, однако в этом правиле
есть исключение. Речь идет о случае, когда абстрактный класс-лист служит общим
пространством имен для глобальных (с областью действия в масштабе класса) атрибутов
и операций, Впрочем, так поступают не очень часто - как правило, для удобства
программистов, работающих с такими языками программирования, которые не поддерживают
объектно-ориентированные технологии.
Мы же советуем избегать подобных случаев, так как они противоречат самому духу
объектно-ориентированного проектирования, внося в модель глобальные зависимости.
Ту же функциональность и большую открытость может обеспечить класс-одиночка.
(См. раздел "Паттерн Singleton" в книге Э. Гамма, Р. Хелм, Р. Джонсон,
Дж. Влиссидес. Приемы обьектно-ориентированного проектирования. Паттерны проектирования.
Спб.: Питер, 2001. С. 131-138.)
Рис. 3. Абстрактный статус суперкласса помогает избежать неясности при моделировании