Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2852
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

p. Основные теоретические пололсения

TWord

font, size L.nmax SetFont()

SetSize()

TWord

font, size, next 0..* SetFont()

SetSize()

TText

n, nmax, MasW(nmax)

Length (), Add (), Del(), SetAttrO, Chang 1{), Chang2()

TText

pFirst;^TWord

<>\ Length (), Add (), Del(), SetAttrO, Chang 1(),

Chang2()

Рис. 9.6. Диаграммы классов для реализации объекта Текст: а - с композицией; 6-Q наполнением

Во втором случае класс TText должен включать список объектов класса TWord (рис. 9.6, б). Ограничения предыдущей реализации будут сняты, но реализация со списком имеет несколько большую трудоемкость, и, кроме то­ го, при обращении к слову по номеру придется каждый раз последовательно отсчитывать нужный элемент. Выбор конкретного варианта реализации зави­ сит от условий решаемой задачи.

Пример 9.3. Разработать классы для реализации объектов Табулятор, Определитель корней и Определитель экстремумов из примера 9.1.

Объекты Табулятор, Определитель корней и Определитель экстремумов отвечают за реализацию методов решения некоторых частных задач при ис­ следовании функций. Они имеют много общего. Попробуем определить это общее.

Любой объект, получив управление, должен ввести диапазон изменения аргумента [а, Ь], решить подзадачу, вывести результаты, а затем вернуть уп­ равление меню операций. Общее поведение и поля объектов опишем в клас­ се TMetod. Основной метод этого класса Run должен реализовывать общее поведение и обеспечивать возможность изменения элементов этого поведе­ ния (решения конкретных подзадач) для объектов классов, которые будут от него наследоваться. Решение конкретной подзадачи реализуем как внутрен­ ний метод Task, вызываемый из метода Run. Этот внутренний метод для класса TMetod определять не будем (абстрактный метод).

Классы для реализации разрабатываемых объектов наследуем от TMetod, переопределяя метод Task и добавляя недостающие поля (рис. 9.7). На диаграмме курсивом показано, что класс TMetod и метод Task являются абстрактными. При необходимости это указывают явно, используя слово «abstruct».

311

Часть 2. Объектно-ориентированное программирование

 

TMetod

 

TMainMenu

 

а, b.real

 

 

Run О

 

 

 

Task 0

 

 

 

f1

 

Опредьллс!

1

1

 

ТТаЫе

TMaxMin

TRoot

 

h:real

eps.real

eps:real

Функция

Task ()

TaskO

Task ()

 

Рис. 9.7. Иерархия классов для реализации объектов

Рис. 9.8. Пример

 

примера

 

ассоциации

Помимо определенных выше, на диаграмме классов показывают также отношения ассоциации между классами, объекты которых обмениваются со­ общениями, но не связаны отношениями композиции или агрегации. Они обозначаются линиями без стрелок. Если сообщения передаются в одну сто­ рону, то направление ассоциации можно показать стрелкой над линией. Кро­ ме того, ассоциации можно дать имя, которое в данном контексте называют ролью (рис. 9.8).

После разработки диаграммы классов переходят к их реализации в кон­ кретном языке программирования. Особенности реализации классов будут обсуждаться в главах 10 - 11.

9.4. Этапы реализации объектно-ориентированного подхода

Процесс разработки программного обеспечения с использованием объ­ ектно-ориентированного подхода включает те же основные этапы, что и с использованием структурного подходы: анализ, проектирование, реализа­ цию и модификацию. Однако процедуры, выполняемые на каждом этапе, не­ сколько меняются. Кроме того, этап реализации при объектном подходе на­ зывают эволюцией, что также связано с его особенностями.

Рассмотрим эти этапы.

Анализ предметной области задачи. Цель анализа - максимально пол­ ное описание задачи. На этом этапе выполняют объектную декомпозицию разрабатываемой системы и определяют основные особенности поведения объектов. Результаты объектной декомпозиции представляют в виде диа­ граммы объектов, на которой показывают основные объекты и сообщения, передаваемые между ними.

Проектирование системы. Логическое проектирование при объектном подходе заключается в разработке структуры классов: определяют поля для хранения составляющих состояния объектов и алгоритмы методов, реализу­ ющих аспекты поведения объектов. При этом используют рассмотренные выше механизмы реализации отношений классов (наследование, компози-

312

p. Основные теоретические полоэюения

ция, наполнение и полиморфизм). Результатом является иерархия или диа­ грамма классов, отражающая отношения между классами и включающая их описание.

Физическое проектирование заключается в объединении описаний клас­ сов в модули, определении способов взаимодействия с оборудованием, с опе­ рационной системой и/или другим программным обеспечением (например, базами данных, сетевыми программами), обеспечении синхронизации про­ цессов для систем параллельной обработки и т.д. Результаты физического проектирования представляют в виде схемы композиции классов в модули, описания интерфейсов для взаимодействия с другими программами и т. п.

Эволюция системы. Эволюция системы - это процесс поэтапной реа­ лизации классов и подключения объектов к системе. Само название этапа подчеркивает поэтапный характер процесса, упрощающий сборку системы.

Реализацию начинают с создания основной программы или проекта бу­ дущего программного продукта. Затем описывают классы и подключают объекты этих классов так, чтобы создать грубый, но, по возможности, рабо­ тающий прототип будущей системы, который тестируют и отлаживают.

Например, на первых этапах эволюции проект может включать только объекты, реализующие основной интерфейс программного продукта. На данном этапе передача сообщений в отсутствующую пока часть системы не выполняется. Отлаженный прототип системы может быть, например, пока­ зан заказчику для уточнения требований.

Далее к проекту подключают следующую группу классов, например, связанных с реализацией некоторого пункта меню. Полученный вариант так­ же тестируется и отлаживается, и так далее, до реализации всех возможнос­ тей системы.

Модификация. Модификация - это процесс добавления новых функци­ ональных возможностей или изменения существующих свойств системы. Как правило, изменения затрагивают реализацию класса, не трогая его ин­ терфейс, что при использовании ООП обычно обходится без особых непри­ ятностей, так как процесс изменений затрагивает локальную область.

Простота модификации позволяет сравнительно легко адаптировать программные системы к изменяющимся условиям эксплуатации, что увели­ чивает время жизни систем, на разработку которых затрачиваются огромные временные и материальные ресурсы.

Особенностью ООП является то, что объект или группа объектов могут разрабатываться отдельно, и, следовательно, их проектирование может нахо­ диться на различных этапах. Например, интерфейсные классы уже реализо­ ваны, а структура классов предметной области еще только уточняется. Обыч­ но проектирование начинается, когда какой-либо фрагмент предметной обла­ сти достаточно полно описан в процессе анализа.

313

10. КЛАССЫ И ОБЪЕКТЫ В BORLAND PASCAL

Объектная модель, реализованная в Borland Pascal, по современным меркам явля­ ется упрощенной, но она позволяет изучить основные приемы объектно-ориентирован­ ного программирования и оценить его достоинства и недостатки.

В настоящей главе рассмотрены средства, используемые для объявления классов и объектов, и принципы создания «универсальных» классов.

ЮЛ. Объявление класса. Поля и методы

С точки зрения синтаксиса класс представляет собой структурный тип данных, в котором помимо полей разрешается описывать прототипы (заго­ ловки) процедур и функций, работающих с этими полями данных. По форме описание класса напоминает запись.

Как уже упоминалось ранее, процедуры и функции, заголовки которых описаны в классе, получили иазваиио методов.

Описание типа класс выполняется следующим образом:

Туре <имя класса> = object <описание полей класса> <прототипы методов>

end;...

Тела методов класса описываются после объявления класса. Причем в заголовке метода можно не повторять списка параметров, но перед именем метода необходимо указать имя класса, отделив его от имени метода точкой:

Procedure <имя класса>.<имя метода>; <локальные ресурсы процедуры>

Begin

<тело процедуры>

End;...

или

314

10. Классы и объекты в Borland Pascal

TRoom Площадь? Комната length, width

Square()

a

б

Рис. 10.1. Объект Комната {а) и реапизующий класс (б)

Function <имя класса>. <имя метода>; <;покальные ресурсы функции>

Begin

<тело процедуры>

End;...

Пример 10.1. Разработать класс для реализации объекта Комната, кото­ рый должен хранить длину и ширину комнаты и отвечать на запрос о площа­ ди комнаты (рис. 10.1, а).

Объект Комната характеризуется двумя параметрами: длиной и шири­ ной, значит соответствующий класс должен включать два поля, в которых эти значения будут храниться (рис. 10.1, б). Единственное сообщение, на ко­ торое должен реагировать объект, - запрос о площади комнаты, следователь­ но, класс должен включать метод-функцию, которая должна возвращать зна­ чение площади комнаты.

Туре TRoom = object

length, width:real;{попя: длина и ширина комнаты} function Square.real; {метод определения площади}

end;

Function TRoom.Square; {тело метода определения площади}

Begin

Square:= length"^ width; End;...

Поскольку поля и методы описаны в одном классе, все поля класса до­ ступны методам класса без дополнительного указания.

Физически это реализуется следующим образом. Каждая переменная - объект данного класса - при объявлении получает свой набор полей класса. Эти поля собраны в запись, внешнее имя которой совпадает с именем объек­ та. Любой метод класса, вызванный для конкретного объекта, неявно получа­ ет специальный параметр Self значением которого является адрес записи, объединяющей все поля этого объекта. Этот параметр иногда называют обоб­ щенным внутренним именем объекта. Реально обращение к полям конкрет­ ного объекта происходит через это обобщенное имя:

315

Часть 2. Объектно-ориентированное программирование

Function TRoom.Square; {тело метода определения площади}

Begin

Square: = Self,length * Self,width; End;...

При необходимости имя Self можно указывать явно, например @Self- адрес записи, содержащей поля объекта (естественно, такое обращение воз­ можно только из методов, вызываемых для конкретного объекта, так как вне объекта это имя не определено).

10.2. Объявление объекта. Инициализация полей

Описав класс, мы можем объявить любое количество объектов этого класса, причем можно объявить отдельные объекты, массивы объектов и ука­ затели на объекты данного класса.

Например:

Var A.'TRoom;

{объект А класса TRoom}

B:array[1..5] of TRoom; {массив объектов типа TRoom}

Type pTRoom=^TRoom;

{тип указателя на объекты класса TRoom}

Var рС: pTRoom;

{указатель на объекты класса TRoom}

Как и для любой другой динамической переменной, для динамического объекта необходимо выделить память, а после его использования -- освобо­ дить память.

Выделение памяти осуществляют процедурой New или функцией New. Например:

New(pC); или pC:=New(pTRoom);...

Для освобождения памяти используют процедуру Dispose. Например:

Dispose(рС);...

Работа с динамическими объектами классов, построенных с использова­ нием наследования со сложным полиморфизмом, имеет свои особенности, и мы вернемся к их рассмотрению в параграфе 11.7.

Обращение к полям и методам объекта. Обращение к полям и мето­ дам объекта выполняется так же, как к полям записей:

• с использованием точечной нотации:

<имя объекта>.<имя поля> или <имя объекта>.<имя метода>;

• с использованием оператора with:

316

10. Классы и объекты в Borland Pascal

with <имя объекта> do

begin

...<имя поля>...

...<имя метода>...

end; ...

Например:

а) v:=A. length; б) s:= A.Square;

в) s:=s+В[i],Square; T)pC4ength:=3;...

Инициализация полей объекта. Поля объекта должны инициализиро­ ваться. Инициализация полей объекта может осуществляться тремя способа­ ми:

• прямым занесением в поле, например:

Program ex;

Type TRoom = object

length, width:real;{поля: длина и ширина комнаты} function Square;real;{мотод определения площади}

end;

Function TRoom.Square; {тело метода определения площади}

Begin

Square:^ length"^ width; End;

Var A:TRoom; {объявляем объект-переменную}

Begin

AJength:-3.5; {инициализируем поля объекта} У4. width:-5J;

1¥гИе1п(*Площадъ комнаты равна \A.Square); End

• с использованием типизированных констант - синтаксис описания совпадает с синтаксисом типизированных констант типа «запись»:

Program ex;

Type TRoom = object

length, width:real;{nonH: длина и ширина комнаты} function Square;real;{MQTOJX определения площади}

end;

317

Часть 2. Объектно-ориентированное программирование

Function TRoom.Square; {тело метода определения площади}

Begin

Square:^ length"^ width; End;

Const

A:TRoom = (length:3.5; width:5.1); {объявляем константу} Begin

WriteLn('Площадь комнаты равна \A.Square);

End

• посредством специального метода - очень часто в качестве такого ме­ тода используют специальную инициализирующую процедуру, которую ре­ комендуется называть Init:

Program ex;

Type TRoom = object

length, width.real;{пояя: длина и ширина комнаты} function Square:real;{MQTOJX определения площади} procedure //i//(7,H';/'^aO;{инициализирующий метод} end;

{метод определения площади}

Function TRoom.Square; Begin

Square: = length* width; End;

{инициализирующий метод}

Procedure TRoontlnit; Begin

length:=l; width:-w; End;

Var A:TRoom; {объявляем объект-переменную}

{основная программа}

Begin

AJnit(3.5y5.1); {инициализируем поля объекта}

WriteLn('Площадь комнаты равна \A.Square); End,

Операция присваивания объектов. Над объектами одного класса оп­ ределена операция присваивания. Физически при этом происходит копирова­ ние полей одного объекта в другой методом «поле за полем»:

Const A:TRoom=(length:3.7;:5,2);

Var B:TRoom;..,

В:=А; {теперь B.length=3.7, а B.width=5.2}

318

10. Классы и объекты в Borland Pascal

Существуют некоторые особенности выполнения операции присваива­ ния для объектов родственных классов и полиморфных объектов. Они опи­ саны в параграфах 11.1 и 11.5.

10.3.Библиотеки классов. Ограничение доступа

кполям и методам

Одним из достоинств ООП является возможность создания библиотек классов, на базе которых затем конструируют классы для реализации объек­ тов реальной задачи. Библиотечные классы при этом описывают в интер­ фейсной части модуля, а тела методов - в разделе реализации.

Например:

Unit Room; Interface

Type TRoom = object

length, width:real; {поля: длина и ширина комнаты} function Square:real; {метод определения площади} procedure /w/Y(7,w.Te(2/j;{инициализирующий метод} end;

Implementation

Function TRoom.Square; {метод определения площади}

Begin

Square:= length"^ width; End;

Procedure TRoom.Init; {инициализирующий метод}

Begin

length: =1; width: =w;

End;

End.

В этом случае основная программа будет подключать соответствующий модуль и работать с классом, его полями и методами, как с рес> рсами библи­ отеки:

Program ex;

Uses /loom;{подключаем модуль с описанием класса TRoom} Var A:TRoom; {объявляем объект-переменную}

Begin

AJnit(3.5y5.1); {инициализируем поля объекта}

WriteLnCКомната: длина= ', AJength,

V ширииа= \ A.width);

319

Часть 2. Объектно-ориентированное программирование

WriteLnCПлощадь комнаты = \A.Square);

End.

В Borland Pascal можно ограничить доступ к полям и методам класса в пределах модуля. Для этого описание класса делится на специальные секции: public-секция, содержащая описание общих или общедоступных полей

и методов класса;

private - секция, содержащая описание внутренних или скрытых полей

иметодов класса.

Вописании класса эти секции могут чередоваться, причем, если секции компонент не указаны, то по умолчанию принимается, что эти компоненты доступны как общие:

Unit <имя модуля>;

Interface

Туре <имя класса>= object

<описание общих полей и методов> private

<описание внутренних полей и методов> public

<описание общих полей и методов> private

<описание внутренних полей и методов>

end;...

Например, в нашем случае, если объекты класса TRoom используются только для получения информации о площади комнаты, то можно поля опи­ сать в секции private, но тогда доступ к этим полям из программы станет не­ возможным:

Unit RoomHiden;

Interface

Type TRoom = object

private {скрытые компоненты класса}

length, width:real; {поля: длина и ширина комнаты} public {общие компоненты класса}

function Square.real;{метод определения площади} procedure Init(l,w:real);{инициализирующий метод} end;

Implementation

Function TRoom.Square; {метод определения площади}

Begin

Square:= length"^ width; End;

320