Гради Буч - Объектно-ориентированный анализ и проектирование с примерами приложений на С++ (1158635), страница 21
Текст из файла (страница 21)
Или предположим, чтопользователь автомата не обратил внимание на предупреждающий сигнал"Бросьте столько мелочи, сколько стоит напиток" и опустил в автоматлишнюю монету. В большинстве случаев автоматы не дружественны кпользователю и радостно заглатывают все деньги.В каждой из таких ситуаций мы видим, что поведение объектаопределяется его историей: важна последовательность совершаемых надобъектом действий. Такая зависимость поведения от событий и от времениобъясняется тем, что у объекта есть внутреннее состояние. Для торговогоавтомата, например, состояние определяется суммой денег, опущенных донажатия кнопки выбора. Другая важная информация - это наборвоспринимаемых монет и запас напитков.На основе этого примера дадим следующее низкоуровневоеопределение:Состояние объекта характеризуется перечнем (обычностатическим) всех свойств данного объекта и текущими (обычнодинамическими) значениями каждого из этих свойств.Одним из свойств торгового автомата является способность приниматьмонеты.
Это статическое (фиксированное) свойство, в том смысле, что оно существенная характеристика торгового автомата. С другой стороны, этомусвойству соответствует динамическое значение, характеризующее количествопринятых монет. Сумма увеличивается по мере опускания монет в автомат иуменьшается, когда продавец забирает деньги из автомата. В некоторыхслучаях значения свойств объекта могут быть статическими (например,заводской номер автомата), поэтому в данном определении использовантермин "обычно динамическими".К числу свойств объекта относятся присущие ему или приобретаемыеим характеристики, черты, качества или способности, делающие данныйобъект самим собой. Например, для лифта характерным является то, что онсконструирован для поездок вверх и вниз, а не горизонтально.
Переченьсвойств объекта является, как правило, статическим, поскольку эти свойствасоставляют неизменяемую основу объекта. Мы говорим "как правило",потому что в ряде случаев состав свойств объекта может изменяться.Примером может служить робот с возможностью самообучения. Роботпервоначально может рассматривать некоторое препятствие как статическое, азатем обнаруживает, что это дверь, которую можно открыть. В такой ситуациипо мере получения новых знаний изменяется создаваемая роботомконцептуальная модель мира.Все свойства имеют некоторые значения.
Эти значения могут бытьпростыми количественными характеристиками, а могут ссылаться на другойобъект. Состояние лифта может описываться числом 3, означающим номерэтажа, на котором лифт в данный момент находится. Состояние торговогоавтомата описывается в терминах других объектов, например, имеющихся вналичии напитков. Конкретные напитки - это самостоятельные объекты,отличные от торгового автомата (их можно пить, а автомат нет, и совершать сними иные действия).Таким образом, мы установили различие между объектами и простымивеличинами: простые количественные характеристики (например, число 3)являются "постоянными, неизменными и непреходящими", тогда как объекты"существуют во времени, изменяются, имеют внутреннее состояние,преходящи и могут создаваться, уничтожаться и разделяться" [б].Тот факт, что всякий объект имеет состояние, означает, что всякийобъект занимает определенное пространство (физически или в памятикомпьютера).Примеры.
Предположим, что на языке C++ нам нужно создатьрегистрационные записи о сотрудниках. Можно сделать это следующимобразом:struct PersonnelRecord {char name[100];intsocialSecurityNurober;char department[10];float salary;};Каждый компонент в приведенной структуре обозначает конкретноесвойство нашей абстракции регистрационной записи. Описание определяет необъект, а класс, поскольку оно не вводит какой-либо конкретный экземпляр.2Для того чтобы создать объекты данного класса, необходимо написатьследующее:PersonnelRecord deb, dave, karen, jim, torn, denise,kaitlyn, krista, elyse;В данном случае объявлено девять различных объектов, каждый изкоторых занимает определенный участок в памяти. Хотя свойства этихобъектов являются общими (их состояние представляется единообразно), впамяти объекты не пересекаются и занимают каждый свое место.
На практикепринято ограничивать доступ к состоянию объекта, а не делать егообщедоступным, как в предыдущем определении класса. С учетом сказанного,изменим данное определение следующим образом:class PersonnelRecord {public:char* employeeName() const;int employeeSocialSecurityNumberf) const;char* employeeDepartment() const;protected:char name[100];int socialSecurityNumber;char department[10];float salary;};Новое определение несколько сложнее предыдущего, но по рядусоображений предпочтительнее.3 В частности, в новом определении2Точнее, это описание определяет структуру в C++, семантика которой соответствуетклассу, у которого все поля открыты. Таким образом, структуры - этонеинкапсулированные абстракции.3К вопросу о стилях: по критериям, которые вводятся в этой главе далее,предложенное определение класса PersonnelRecord - это далеко не шедевр.
Мы хотимздесь только показать семантику состояния класса. Иметь в классе функцию, котораявозвращает значение char*, часто опасно, так как это нарушает парадигму защитыпамяти: если метод отводит себе память, за которую получивший к ней доступ клиентреализация класса скрыта от других объектов. Если реализация класса будет вдальнейшем изменена, код придется перекомпилировать, но семантическиклиенты не будут зависеть от этих изменении (то есть их код сохранится).Кроме того, решается также проблема занимаемой объектом памяти за счетявного определения операций, которые разрешены клиентам над объектамиданного класса.
В частности, мы даем всем клиентам право узнать имя, кодсоциальной защиты и место работы сотрудника, но только особым клиентам (аименно, подклассам данного класса) разрешено устанавливать значенияуказанных параметров. Только этим специальным клиентам разрешен доступк сведениям о заработной плате. Другое достоинство последнего определениясвязано с возможностью его повторного использования. В следующем разделемы увидим, что механизм наследования позволяет повторно использоватьабстракцию, а затем уточнить и многими способами специализировать ее.В заключение скажем, что все объекты в системе инкапсулируютнекоторое состояние, и все состояние системы инкапсулировано в объекты.Однако, инкапсуляция состояния объекта - это только начало, которогонедостаточно, чтобы мы могли охватить полный смысл абстракций, которыемы вводим при разработке.
По этой причине нам нужно разобраться, какобъекты функционируют.ПоведениеЧто такое поведение. Объекты не существуют изолированно, аподвергаются воздействию или сами воздействуют на другие объекты.Поведение - это то, как объект действует и реагирует; поведениевыражается в терминах состояния объекта и передачи сообщений.Иными словами, поведение объекта - это его наблюдаемая ипроверяемая извне деятельность.Операцией называется определенное воздействие одного объекта надругой с целью вызвать соответствующую реакцию.
Например, клиент можетактивизировать операции append и pop для того, чтобы управлять объектомочередью (добавить или изъять элемент). Существует также операция length,которая позволяет определить размер очереди, но не может изменить этозначение.
В чисто объектно-ориентированном языке, таком как Smalltalk,принято говорить о передаче сообщений между объектами. В языках типаC++, в которых четче ощущается процедурное прошлое, мы говорим, что одинобъект вызывает функцию-член другого. В основном понятие сообщениесовпадает с понятием операции над объектами, хотя механизм передачиразличен. Для наших целей эти два термина могут использоваться каксинонимы.В объектно-ориентированных языках операции, выполняемые надданным объектом, называются методами и входят в определение классаобъекта.
В C++ они называются функциями-членами. Мы будем использоватьэти термины как синонимы.Передача сообщений - это одна часть уравнения, задающегоповедение. Из нашего определения следует, что состояние объекта такжевлияет на его поведение. Рассмотрим торговый автомат. Мы можем сделатьвыбор, но поведение автомата будет зависеть от его состояния. Если мы неопустили в него достаточную сумму, скорее всего ничего не произойдет. Еслиже денег достаточно, автомат выдаст нам желаемое (и тем самым изменитсвое состояние). Итак, поведение объекта определяется выполняемыми надне отвечает, результатом будет замусоривание памяти. В наших системах мыпредпочитаем использовать параметризованный класс строк переменной длины,который можно найти в базовой библиотеке классов, вроде той, что описана в главе 9.И еще: классы - это больше чем структуры из С с синтаксисом классов C++; какобъясняется в главе 4, классификация требует определенного согласования структурыи поведения.ним операциями и его состоянием, причем некоторые операции имеютпобочное действие: они изменяют состояние.