7.5.3.1. Направление параметра
Для параметров операции может быть задано направление:
операция( in p1:Integer, inout p2:Integer, out p3:Integer, return p4:Integer, return p5:Integer )
Если направление не указано, по умолчанию оно принимает значение in (в). Семантика направления параметра приведена в табл. 7.6.
Семантика значений in, inout (в из) и out (из) довольно проста, а вот return (возвратить) возможно потребует большего внимания.
Обычно ожидается, что функция возвращает один объект, как показа но ниже:
maximumValue = max( a, b )
minimumValue = min( a, b )
направление имяПараметра : типПараметра = значениеПоУмолчанию
Рис. 7.11. Синтаксис параметров операции
7.5. Нотация классов в UML
167
где a, b, maximumValue (максимальное значение) и minimumValue (мини мальное значение) – целые числа. Обычный синтаксис операции под держивает именно эту ситуацию: каждая операция обычно имеет только одно возвращаемое значение. Как мы видели, в UML такие
«обычные» операции можно смоделировать следующим образом:
maximumValue( a:Integer, b:Integer ) : Integer
Таблица 7.6
Однако в некоторых языках операции могут возвращать более одного значения. Например, в языке программирования Python можно было бы написать:
maximumValue, minimumValue = maxMin( a, b )
где maxMin( a, b ) возвращает два значения – максимальное и минималь ное. В UML это можно смоделировать следующим образом:
maxMin( in a: Integer, in b:Integer, return maxValue:Integer, return minValue:Integer )
Как видим, направление return параметра позволяет моделировать си туации, когда операция возвращает более одного значения.
Возвращаемые параметры могут быть перечислены и после имени опе рации:
maxMin( in a: Integer, in b:Integer ) : Integer, Integer
Параметр
Семантика
in p1:Integer
Применяется по умолчанию.
Операция использует p1 как входной параметр.
Значение p1 каким то образом используется операцией.
Операция не изменяет p1.
inout p2:Integer
Операция принимает p2 как параметр ввода/вывода.
Значение p2 каким то образом используется операцией.
и
принимает выходное значение операции.
Операция может изменять p2.
out p3:Integer
Операция использует p3 как выходной параметр.
Параметр служит хранилищем для выходного значения операции.
Операция может изменять p3.
return p4:Integer
Операция использует p4 как возвращаемый параметр.
Операция возвращает p4 как одно из своих возвращаемых значений.
return p5:Integer
Операция использует p5 как возвращаемый параметр.
Операция возвращает p5 как одно из своих возвращаемых значений.
168Глава 7. Объекты и классы
В данном случае применение ключевого слова return было бы плохим стилем, поскольку возвращаемые параметры и так явно выделены.
На самом деле направления параметров являются вопросом проекти рования, поэтому обычно во время анализа о них не заботятся (если только не используется OCL).
Направления параметров имеют большое значение при проектирова нии, особенно если речь идет о генерации кода. Генераторы кода будут проецировать направления параметров UML в конкретную семантику передачи параметров в целевом языке программирования.
7.5.3.2. Значения параметров по умолчаниюДля параметра операции может быть задано значение, применяемое по умолчанию. Если при вызове операции параметру не присваивается зна чение, используется значение по умолчанию.
На рис. 7.12 показано, как задаются применяемые по умолчанию зна чения. Здесь в классе
Canvas имеется две операции: drawCircle(...) (нари совать круг) и drawSquare(...) (нарисовать квадрат), отрисовывающие на экране круг и квадрат соответственно. Для параметра origin (начало от счета) задается значение по умолчанию
Point(0,0). Если при вызове этих
операций данный параметр будет опущен, фигуры будут отрисованы на экране относительно точки
{0,0}.
На самом деле применяемые по умолчанию значения являются вопро сом проектирования; во время анализа они используются редко.
7.5.3.3. Расширенный синтаксис операцииСемантику операций можно расширить, предваряя их стереотипами и дополняя помеченными значениями.
«стереотип» операция(…) { метка1 = значение1, метка2 = значение2, … }
Можно также ввести помеченные значения в параметры операций, но мы ни разу не сталкивались с ситуацией, когда это было бы полезно.
7.5.3.4. Операции запросаВ каждой операции есть свойство isQuery. Если в инструменте модели рования этому свойству присвоено значение true, операция является операцией запроса. Это означает, что она
не имеет побочных эффектови не меняет состояние объекта, в котором вызывается. Операция, воз
Canvas drawCircle( origin: Point = Point( 0, 0 ), radius : Integer )
drawSquare( origin: Point = Point( 0, 0 ), size : Dimension )
Рис. 7.12. Задание параметров по умолчанию 7.5. Нотация классов в UML
169вращающая значение атрибута, называется операцией запроса. Ее свой ству isQuery должно быть присвоено значение true.
По умолчанию isQuery имеет значение false. Обычно isQuery задается при проектировании. Однако если в UML моделях применяется OCL (см.
главу 25), важно обозначить операции запроса, потому что выражения
OCL не могут менять состояния системы и поэтому могут использовать
только операции запроса. Если задано isQuery, компиляторы OCL мо гут проверять, какие операции (допустимые или нет) вызывают OCL
выражения.
Более или менее универсальный способ наименования операций за проса – ставить приставку get перед именем того, что вы запрашивае те. Пример приведен на рис. 7.13.
7.5.4. Синтаксис стереотипа классаСтереотипы могут отображаться по разному (рис. 7.14). Однако боль шинство разработчиков моделей используют имя, заключенное в ка вычки (
«имя cтереотипа»), или пиктограмму. Другие варианты не так широко используются, и инструментальные средства моделирования часто налагают ограничения.
Стереотипы также могут быть ассоциированы с цветами или текстура ми, но это очень плохая практика. У некоторых читателей, имеющих проблемы со зрением или не различающих цвета, могут возникнуть сложности с пониманием таких диаграмм. Кроме того, чаще всего диа граммы распечатываются в черно белом варианте.
BankAccount getBalance() : double операция запроса
(isQuery = true)
имя атрибута начинается с большой буквы возвращает значение атрибута balance balance : double
Рис. 7.13. Именование операций запросаTicket
«entity»
Ticket
«entity»
Ticket
Ticket предпочтительное пиктограмма стереотип предпочтительное
Рис. 7.14. Варианты отображения стереотипов 170Глава 7. Объекты и классы
7.6. Область действияАтрибуты и операции, область действия которых – экземпляр, принад лежат или выполняются определенным объектом.
До сих пор мы видели, что у объектов есть собственные копии атрибу тов, определенных в их классе. Таким образом, атрибуты разных объ ектов могут принимать разные значения. Аналогично все операции,
рассмотренные до сих пор, выполняются определенными объектами.
Это обычная ситуация. Говорят, что эти атрибуты и операции имеют
область действия – экземплярАтрибуты и операции, область действия которых – класс, принадлежат или выполняются во всех объектах данного класса.
Однако иногда нужно определить атрибуты, которые имеют единствен ное, общее для
всех объектов класса значение. И нужны операции (как операции создания объектов), не относящиеся ни к одному конкретно му экземпляру класса. Говорят, что такие атрибуты и операции имеют
область действия – класс. Свойства, область действия которых –
класс, обеспечивают набор глобальных характеристик объектов класса.
7.6.1. Область действия – класс и область действия – экземплярОбозначение атрибутов и операций с областями действия класс и эк земпляр показано на рис. 7.15. Семантика таких атрибутов и опера ций приведена в табл. 7.7.
7.6.2. Область действия определяет возможность доступаВозможность доступа операции к другому свойству класса определяет ся областью действия операции и областью действия свойства, к кото рому пытаются получить доступ.
Операции, область действия которых – экземпляр, могут организовы вать доступ к другим атрибутам и операциям с такой же областью дей
+create( accNumber : String )
+getAccountNumber : String incrementCount()
+decrementCount()
+getCount() : int
BankAccount accountNumber : String count : int = 0
область действия –
экземпляр область действия –
класс (подчеркнуто)
Рис. 7.15. Атрибуты и операции с областями действия класс и экземпляр 7.7. Создание и уничтожение объектов171ствия, а также ко всем атрибутам и операциям, область действия кото рых – класс.
Операции, область действия которых – класс, могут организовывать доступ
только к атрибутам и операциям, имеющим область действия –
класс. Операции уровня класса не имеют доступа к операциям уровня экземпляра, потому что:
•возможно, еще не создано ни одного экземпляра класса;
•даже если экземпляры класса существуют, неизвестно, какой из них использовать.
Таблица 7.77.7. Создание и уничтожение объектовКонструкторы – это специальные операции, создающие новые объекты.
Область их действия – класс.
Область действия – экземплярОбласть действия – классАтрибуты По умолчанию область действия атрибутов – экземпляр.
Для атрибутов может быть опре делена область действия класс.
Каждый объект класса получа ет собственную копию атрибу тов, область действия которых –
экземпляр.
Каждый объект класса исполь зует одну и ту же единственную копию атрибутов класса.
Следовательно, значения атри бутов экземпляра могут быть разными в каждом объекте.
Следовательно, значения атри бутов класса во всех объектах одинаковые.
Операции По умолчанию область действия операций – экземпляр.
Для операций может быть опре делена область действия – класс.
Каждый вызов операции экзем пляра касается конкретного эк земпляра класса.
Вызов операции класса не каса ется конкретного экземпляра класса. Операции уровня класса можно рассматривать как при меняемые к самому классу.
Невозможно вызвать операцию экземпляра, не имея в распоря жении экземпляра класса. Без условно, это означает, что
нель зя использовать операции, об ласть действия которых – эк земпляр, для создания объектов этого класса: никогда не полу чится создать первый объект.
Инициировать операции класса можно, даже не имея экземпля ра класса; это идеально подхо дит для операций создания объ ектов.
172Глава 7. Объекты и классы
Конструкторы – это специальные операции, создающие новые экземп ляры классов. Эти операции
должны иметь область действия – класс.
Если бы они были уровня экземпляра, не было бы возможности соз дать первый экземпляр класса.
Конструкторы – забота проектирования. Обычно их
не показывают на аналитических моделях.
В разных языках программирования действуют разные стандарты именования конструкторов. Абсолютно универсальный подход – на зывать конструктор просто create(…) (создать). Это делает понятным назначение данной операции. Однако языки Java, C# и C++ требуют,
чтобы имя конструктора совпадало с именем класса.
У класса может быть несколько конструкторов с одинаковыми имена ми, но с разным набором параметров. Конструктор без параметров на зывают
применяемым по умолчанию конструктором (
default constructor). Параметры конструктора можно использовать для иници ализации значений атрибутов в момент создания объекта.
На рис.7.16 показан простой пример класса
BankAccount (банковский счет). При каждом создании объекта
BankAccount в качестве параметра в его конструктор должно передаваться значение типа
String. Эта стро ка используется для задания атрибута accountNumber (номер счета) (на пример, значение
“XYZ001002”). Тот факт, что конструктору класса Bank
Account необходим параметр, говорит о том, что создать объект BankAc count,
не определив этот параметр,
нельзя. Это гарантирует задание ат рибута accountNumber каждого объекта BankAccount в момент создания объекта. Это очень хороший стиль.
В аналитических моделях обычно не занимаются конструкторами
(и тем более деструкторами). Они не имеют ни влияния, ни отношения к бизнес семантике класса. Если все таки есть желание обозначить операции создания, можно ввести операцию create() без параметров как структурный нуль. Или можно указать только параметры, имею щие в перспективе существенное значение.
Когда дело дойдет до детального проекта,
необходимо будет опреде лить имя, типы параметров и возвращаемый тип
каждой операции
(см. раздел 17.4). Сюда входит и явное описание конструктора и де структора.
Уничтожение объекта не такая простая операция, как его создание.
В разных ОО языках программирования семантика уничтожения объ
BankAccount универсальное имя конструктора стандарт Java/C#/C++
BankAccount
+BankAccount( accNumber : String )
+create( accNumber : String )
Рис. 7.16. Именование конструктора
7.7. Создание и уничтожение объектов
173
екта разная. Более подробно создание и уничтожение объектов рас сматриваются в следующих двух разделах.
7.7.1. Конструкторы – пример класса ClubMember
Пример класса
ClubMember (член клуба) (рис. 7.17) показывает обычное применение атрибутов и операций уровня класса. Этот класс описывает некий член клуба. Атрибут numberOfMembers (количество членов) – за крытый (private) атрибут класса типа int. Следовательно, этот атрибут используется совместно всеми объектами класса
ClubMember. Его значе ние для каждого из этих объектов будет одинаковым.
При создании атрибута numberOfMembers ему присваивается начальное значение, равное нулю. Далее, если бы это был атрибут экземпляра,
каждый объект при создании получал бы собственную копию этого ат рибута. Однако область действия этого атрибута – класс. Значит, су ществует только одна его копия, и эта единственная копия инициали зируется только один раз. Когда именно это происходит, зависит от языка реализации. Мы должны знать лишь то, что атрибут инициали зируется со значением нуль при запуске программы.
Предположим, что в операции create(...) происходит вызов операции класса incrementNumberOfmembers() (увеличить число членов). Как можно ожидать из ее имени, эта операция увеличивает значение атрибута клас са numberOfMembers. При каждом создании экземпляра класса numberOf
Members увеличивается на единицу. В класс введен счетчик! С помощью операции класса getNumberOfMembers() (получить количество членов)
можно запросить значение атрибута numberOfMembers. Данная операция возвращает число, равное количеству созданных объектов
ClubMember.
7.7.2. Деструкторы – пример класса ClubMember
Деструкторы – это специальные операции, которые «наводят порядок»
при уничтожении объектов.
+create( number : String, name : String )
+getMembershipNumber() : String
+getMemberName() : String incrementNumberOfMembers
+decrementNumberOfMembers
+getNumberOfMembers() : int
ClubMember membershipNumber : String memberName : String numberOfMembers : int = 0
Рис. 7.17. Применение атрибутов и операций уровня класса
174Глава 7. Объекты и классы
Что происходит, если программа создает
и уничтожает объекты
Club
Member? Очевидно, что значение атрибута numberOfMembers быстро поте ряет смысл. Исправить эту ситуацию можно, введя в класс операцию для уменьшения значения атрибута numberOfMembers (рис. 7.17) и обес печив ее вызов при каждом уничтожении экземпляра класса
ClubMember.
В некоторых ОО языках программирования есть специальные опера ции уровня экземпляра, называемые деструкторами, которые автома тически вызываются в момент уничтожения объекта. Например, в С++
деструктор всегда имеет форму
ИмяКласса (списокПараметров). В С++
операция уничтожения
гарантированно вызывается в момент уничто жения объекта.
В Java есть аналогичная возможность: каждый класс имеет операцию под названием finalize(), которая вызывается при окончательном унич тожении объекта. Но сама программа явно не уничтожает объекты.
Этим занимается автоматический сборщик мусора. Вам известно, что finalize() будет вызван, но вы не знаете,
когда это произойдет! Конечно,
это не подходит для нашего простого приложения со счетчиком. Здесь приходится самостоятельно уменьшать значение атрибута number
OfMembers, вызывая операцию уровня класса decrementNumberOfMem bers(), когда работа с объектом завершена и он отправляется в сборщик мусора.
C# имеет аналогичную Java семантику уничтожения, только опера ция называется
Finalize().
7.8. Что мы узналиВ этой главе были представлены основные сведения по классам и объ ектам, которые используются далее в книге. Классы и объекты – это строительные блоки ОО систем, поэтому важно всесторонне и детально их понимать.
Мы узнали следующее:
•Объекты – это образующие единое целое элементы, сочетающие в се бе данные и функции.
•Инкапсуляция – данные, находящиеся внутри объекта, скрыты.
Манипулировать ими можно, только инициируя одну из функций объекта.
•Операции – это спецификации функций объекта, создаваемые во время анализа.
•Методы – это реализации функций объекта, создаваемые во вре мя реализации.
•Каждый объект – это экземпляр класса.
Класс определяет общие характеристики, присущие всем объектам этого класса.
7.8. Что мы узнали
175•У каждого объекта есть следующие характеристики:
•Идентичность – уникальность существующего объекта: вы ис пользуете объектные ссылки для однозначного указания на кон кретный объект.
•Состояние – значимый набор значений атрибутов и отношений объекта в определенный момент времени.