Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование на языке высокого уровня Паскаль. Учебное пособие для СПО
.pdf
Подводя итог сказанному выше, сформулирую преимущества ООП:
1. использование в программах понятий, более близких к
предметной области;
2. более простая структура программы в результате инкапсуляции, то
есть объединения свойств и поведения объекта и скрытия деталей
его реализации;
3. возможность повторного использования кода за счет
наследования;
4. сравнительно простая возможность модификации программы;
5. возможность создания библиотек объектов.
Эти преимущества проявляются при создании программ большого
объема и классов программ. Однако создание объектноориентированной программы представляет собой весьма непростую
задачу, поскольку в процесс добавляется этап разработки иерархии
объектов, а плохо спроектированная иерархия приводит к появлению
сложных и запутанных программ.
Чтобы эффективно использовать готовые объекты, необходимо освоить
большой объем достаточно сложной информации. Нашу задачу
облегчает то, что объектная модель Паскаля по сравнению с другими
языками является упрощенной. Тем не менее на ее примере удобно
изучить основные положения ООП, не увязнув в многообразии
возможностей и деталей.
Описание объектов
Объект — это тип данных, поэтому он определяется в разделе описания
типов. В других языках объектный тип называют классом. Объект
похож на тип record, но кроме полей данных в нем можно описывать
методы. Методами называются подпрограммы, предназначенные для
работы с полями объекта. Внутри объекта описываются только
заголовки методов.
type имя = object
[ private ]
описание полей
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
121

[ public ]
заголовки методов
end;
Поля и методы называются элементами объекта. Их видимостью
управляют директивы private и public. Ключевое слово
private ( закрытые ) ограничивает видимость перечисленных после
него элементов файлом, в котором описан объект. Действие директивы
распространяется до другой директивы или до конца объекта. В объекте
может быть произвольное количество разделов private и public.
По умолчанию все элементы объекта считаются видимыми извне, то
есть являются public ( открытыми ). Этим Паскаль отличается от
других, более современных языков программирования.
Поля объекта описываются аналогично обычным переменным: для
каждого поля задается его имя и тип. Тип может быть любым, кроме
типа того же объекта, но может быть указателем на этот тип. Значения
полей определяют состояние объекта.
При определении состава методов исходят из требуемого поведения
объекта. Каждое действие, которое должен выполнять объект,
оформляется в виде отдельной процедуры или функции. Рассмотрим в
качестве примера объект, моделирующий персонаж компьютерной
игры.
type monster = object
procedure init(x_, y_, health_, ammo_ : word);
procedure attack;
procedure draw;
procedure erase;
procedure hit;
procedure move(x_, y_ : word);
private
x, y : word;
health, ammo : word;
color : word;
end;
В этом объекте пять полей данных. Поля x и y представляют собой
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
122

местоположение объекта на экране, health хранит состояние
здоровья, ammo — боезапас, а color — цвет. Поля описаны в
разделе private, так как эта информация относится к внутренней
структуре объекта.
Допустим, что нашему герою придется перемещаться по экрану,
атаковать другие объекты и терять при этом здоровье и оружие.
Каждому действию соответствует свой метод. Методы описаны в
разделе public (по умолчанию), потому что они составляют
интерфейс объекта.
Вся внешняя информация, необходимая для выполнения действий с
объектом, должна передаваться методам в качестве параметров.
Параметры могут иметь любой тип, в том числе и тип того же объекта.
Имена параметров не должны совпадать с именами полей объекта.
Описание методов (текст подпрограмм) размещается вне объекта в
разделе описания процедур и функций, при этом имени метода
предшествует имя объекта, отделенное точкой, например:
procedure monster.init(x_, y_, health_, ammo_ : word);
begin
x := x_; y := y_;
health := health_;
ammo := ammo_;
color := yellow;
end;
procedure monster.draw;
begin
setcolor(color); outtextXY(x, y, '@');
end;
Перед использованием объект требуется инициализировать, то есть
присвоить начальные значения его полям и, возможно, выполнить
другие подготовительные действия. В документации Borland Pascal
процедуре инициализации объекта рекомендуется давать имя init.
Обратите внимание, что поля объекта используются внутри методов
непосредственно, без указания имени объекта.
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
123

Процедура draw предназначена для вывода изображения объекта на
экран. Для простоты примем, что изображение монстра представляет
собой просто символ "собаки" @.
Методы представляют собой разновидность подпрограмм, поэтому
внутри них можно описывать локальные переменные. Принцип здесь
точно такой же, как и при написании обычных подпрограмм: если
переменная используется для временного хранения данных только
внутри метода, ее следует описывать в этом методе как локальную.
Как правило, поля объекта объявляют как private, а методы как
public, однако это не догма. Если поле объекта представляет собой
свойство, которое концептуально входит в интерфейс объекта, и
пользователь должен иметь право устанавливать и получать его без
каких-либо ограничений, логично поместить его в раздел public. И
наоборот: если метод предназначен только для вызова из других
методов, его лучше скрыть от посторонних глаз в разделе private.
Для реализации принципа инкапсуляции, то есть ограничения
видимости элементов, объекты обычно описывают в модулях. Тип
объекта определяется в интерфейсном разделе модуля, а тексты методов
объекта — в разделе реализации.
Объекты можно описать и в разделе реализации модуля. Они
подчиняются тем же ограничениям, что и любые другие типы,
определенные в этом разделе. Объект, определенный в интерфейсном
разделе модуля, может иметь потомков, определенных в разделе
реализации. Если модуль В использует модуль А, в модуле В могут
определяться потомки любых объектов, описанных в интерфейсном
разделе модуля А.
ВНИМАНИЕ В отличие от остальных, объектный тип можно
определять только в разделе описания типов самого внешнего блока
программы или модуля.
Описание объекта monster в модуле приведено в пример 6.1.
unit monsters;
interface
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
124

uses Graph;
type monster = object
procedure init(x_, y_, health_, ammo_ : word);
procedure attack;
procedure draw;
procedure erase;
procedure hit;
procedure move(x_, y_ : word);
private
x, y : word;
health, ammo : word;
color : word;
end;
implementation
{ ----------------------- реализация методов объекта monster ------------------- }
procedure monster.init(x_, y_, health_, ammo_ : word);
begin
x := x_; y := y_;
health := health_;
ammo := ammo_;
color := yellow;
end;
procedure monster.attack; { ------------------------------- monster.attack ------ }
begin
if ammo = 0 then exit;
dec(ammo); setcolor(color); outtextXY(x + 15, y, 'ба-бах!');
end;
procedure monster.draw; { ------------------------------- monster.draw -------- }
begin
setcolor(color); outtextXY(x, y, '@');
end;
procedure monster.erase; { ------------------------------- monster.erase ------- }
begin
setcolor(black); outtextXY(x, y, '@');
end;
procedure monster.hit; { ------------------------------- monster.hit --------- }
begin
if health = 0 then exit;
dec(health);
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
125

if health = 0 then begin color := red; draw; exit; end;
attack;
end;
procedure monster.move(x_, y_ : word); { ------------------ monster.move -------- }
begin
if health = 0 then exit;
erase; x := x_; y := y_; draw;
end;
end.
Листинг 6.1. Описание объекта monster
Для стирания изображения объекта с экрана от выводится поверх
старого цветом фона (метод erase ). Перемещение объекта (метод
move ) выполняется путем стирания на старом месте и отрисовки на
новом.
Атака (метод attack ) реализована схематично: если имеется
ненулевой боезапас, он уменьшается на единицу, после чего выводится
диагностическое сообщение. Если объект атакован (метод hit ), он
теряет единицу здоровья, но атакует в ответ, а при потере последней
единицы здоровья выводится на экран красным цветом. Объект,
потерявший в сражении все здоровье, двигаться и атаковать не может.
Экземпляры объектов
Переменная объектного типа называется экземпляром объекта. Часто
экземпляры называют просто объектами. Время жизни и видимость
объектов зависят от вида и места их описания и подчиняются общим
правилам Паскаля. Экземпляры объектов, так же как и переменные
других типов, можно создавать в статической или динамической
памяти, например:
var Vasia : monster; { описывается статический объект }
pm : ^monster; { описывается указатель на объект }
...
new(pm); { создается динамический объект }
Можно определять массивы объектов или указателей на объекты и
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
126

создавать из них динамические структуры данных. Если объектный тип
описан в модуле, для создания в программе переменных этого типа
следует подключить модуль в разделе uses:
uses graph, monsters;
Доступ к элементам объекта осуществляется так же, как к полям записи:
либо с использованием составного имени, либо с помощью оператора
with.
Vasia.erase;
with pm^ do begin init(100, 100, 30); draw; end;
При обращении указывается имя экземпляра объекта, а не имя типа.
Если поля объекта являются открытыми или объектный тип описан в
той же программной единице, где используется, к полям можно
обращаться так же, как к методам:
pm^.x := 300; { если бы x было public }
Если объект описан в модуле, получить или изменить значения
элементов со спецификатором private в программе можно только
через обращение к соответствующим методам.
При создании каждого объекта выделяется память, достаточная для
хранения всех его полей. Методы объекта хранятся в одном экземпляре.
Для того чтобы методу было известно, с данными какого экземпляра
объекта он работает, при вызове ему в неявном виде передается
параметр self, определяющий место расположения данных этого
объекта. Фактически внутри метода обращение к полю x объекта имеет
вид self.x. При необходимости имя self можно использовать
внутри метода явным образом, например @self представляет собой
адрес начала области, в которой хранятся поля объекта.
Объекты одного типа можно присваивать друг другу, при этом
выполняется поэлементное копирование всех полей. Кроме того, в
Паскале определены правила расширенной совместимости типов
объектов. Все остальные действия выполняются над отдельными
полями объектов.
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
127

В пример 6.2 приведен пример программы, использующей модуль
monsters.
program test_monster;
uses graph, crt, monsters;
var Vasia : monster; { 1 }
x, y : word;
gd, gm : integer;
begin
gd := detect; initgraph(gd, gm, '...');
if graphresult <> grOk then begin
writeln('ошибка инициализации графики'); exit end;
Vasia.init(100, 100, 10, 10); { 2 }
Vasia.draw; { 3 }
Vasia.attack; { 4 }
readln;
x := 110;
while x < 200 do begin
Vasia.move(x, x); inc(x, 7); { 5 }
Vasia.hit; { 6 }
delay(200);
end;
readln;
end.
Листинг 6.2. Пример использования модуля monsters
Для тестирования объекта monster в программе определена
переменная Vasia типа monster (оператор 1). Для нее вызываются
процедуры инициализации (2), отрисовки (3) и атаки (4), а затем
перемещения по экрану (5) с имитацией попадания в объект при
каждом перемещении (6). Таким образом проверяется
работоспособность всех методов объекта.
Пример программы, в которой используется массив объектов типа
monster, приведен в пример 6.3. Все объекты инициализируются
случайными значениями, а затем начинают хаотически перемещаться по
экрану. Если два монстра оказываются на достаточно близком
расстоянии друг от друга, они считаются атакованными (для обоих
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
128

экземпляров вызывается метод hit ). Выход из этой в высшей степени
медитативной программы, которую можно назвать "монстры от испуга
скушали друг друга", выполняется по нажатию любой клавиши.
<$Mmonster _game>program dinner;
uses graph, crt, monsters;
const n = 30;
var stado : array [1 .. n] of monster;
x, y : array [1 .. n] of integer;
gd, gm : integer;
i, j : word;
begin
gd := detect; initgraph(gd, gm, '...');
if graphresult <> grOk then begin
writeln('ошибка инициализации графики'); exit end;
randomize;
for i := 1 to n do begin
stado[i].init(random(600), random(440), random(10), random(8));
stado[i].draw;
end;
repeat
for i := 1 to n do begin
x[i] := random(600); y[i] := random(440);
stado[i].move(x[i], y[i]);
end;
for i := 1 to n – 1 do
for j := i + 1 to n do
if (abs(x[i] – x[j]) < 15) and (abs(y[i] – y[j]) < 15)
then begin
stado[i].hit; stado[j].hit;
end;
delay(200);
until keypressed;
end.
Листинг 6.3. Пример использования массива объектов типа
monster
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
129

Иерархии объектов. Работа с объектами в
динамической памяти
Описание потомков объекта. Наследование полей и методов. Раннее и
позднее связывание. Механизм виртуальных методов. Конструкторы и
деструкторы. Размещение объектов в динамической памяти.
Полиморфные объекты. Контейнер (список) полиморфных объектов.
Наследование
Презентацию к данной работе Вы можете скачать здесь скачать:
http://old.intuit.ru/department/pl/prinpas/7/Pascal_7.zip.
Управлять большим количеством разрозненных объектов достаточно
сложно. С этой проблемой можно справиться путем упорядочивания и
ранжирования объектов, то есть объединяя общие для нескольких
объектов свойства в одном объекте и используя этот объект в качестве
базового.
Эту возможность предоставляет механизм наследования. Он позволяет
строить иерархии, в которых объекты-потомки получают свойства
объектов-предков и могут дополнять их или изменять. Таким образом,
наследование обеспечивает возможность повторного использования
кода.
Объекты, расположенные ближе к началу иерархии, объединяют в себе
наиболее общие черты для всех нижележащих объектов. По мере
продвижения вниз по иерархии объекты приобретают все больше
конкретных особенностей.
Объект в Паскале может иметь произвольное количество потомков и
только одного предка. При описании объекта имя его предка
записывается в круглых скобках после ключевого слова object.
Допустим, нам требуется ввести в игру еще один тип персонажей,
который должен обладать свойствами объекта monster, но подругому выглядеть и атаковать. Будет логично сделать новый объект
потомком объекта monster. Проанализировав код методов этого
Программирование на я зыке высокого уровня ПаскальТ.А. Павловская
130
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
