Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабраб_3.DOC
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
128 Кб
Скачать

Лабораторная работа №3

Объектно-ориентированное программирование

Цель работы – овладение практическими приемами и навыками разработки и создания программ посредством иерархически связанных классов.

  1. Теоретическая часть

1.1. Введение

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

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

ООП опирается на три основных понятия:

  • инкапсуляция;

  • наследование;

  • полиморфизм.

1.2.Объект и инкапсуляция

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

Инкапсуляция - объединение данных с процедурами и функциями для создания нового типа данных - объекта. Связанные с объектом процедуры и функции называются методами. Таким образом, поля данных объекта - это то, что объект "знает", его методы - это то, что объект делает.

Для описания объектов используется зарезервированное слово OBJECT. Описание объекта помещается в разделе описания типов. Вначале описываются все инкапсулированные в объекте данные, а затем - методы доступа к этим данным. Сами методы при описании объекта не раскрываются, указываются лишь заголовки. Методы описываются ниже по тексту программы.

В рассмотренном ниже примере тип объекта "координаты точки" может быть определен следующим образом:

Type Location = Object

X,Y: Integer; {данные}

Procedure Init(InitX, InitY: Integer); {заголовки методов}

Function GetX: Integer;

Function GetY: Integer;

End;

{описание методов}

Procedure Location.Init(InitX, InitY: Integer);

Begin

X:=InitX;

Y:=InitY;

End;

Function Location.GetX: Integer;

Begin

GetX:=X; {получение координаты Х текущей позиции на экране}

End;

Function GetY: Integer;

Begin

GetY:=Y; {получение координаты У текущей позиции на экране}

End;

1.3. Иерархия объектов и наследование

Предположим, что мы хотим высветить точку на экране в позиции, описанной типом LOCATION. Определим тип POINT, который содержит булевское поле, указывающее, светится ли пиксель в данной позиции. Так как все точки должны содержать позицию, мы говорим, что тип POINT - это тип, порожденный типом LOCATION. POINT наследует все, что имеет LOCATION и добавляет в него нечто новое (признак светимости):

Type Location = Object

X,Y: Integer; {данные}

Procedure Init(InitX, InitY: Integer); {заголовки методов}

Function GetX: Integer;

Function GetY: Integer;

End;

Point = Object(Location)

Visible: Boolean;

End;

В качестве примера построим иерархию объектов Координаты - Точка - Квадрат (Lоcation - Point - Square). Удобно определять объекты в модулях, причем тип объекта описывается в интерфейсной части модуля, а тела процедур-методов типа объекта - в разделе модуля Implementation.

Пример 7.1. Этот модуль определяет объекты Lоcation, Point и Square.

unit obj1_OOP;

interface

uses graph;

type location = object

x,y: integer;

procedure init(X1,Y1:integer);

function getX: integer;

function getY: integer;

end;

point = object(location)

procedure init(X1,Y1:integer);

visible: boolean;

procedure show;

procedure hide;

procedure shift(X1,Y1:integer);

end;

square = object(point)

side: integer;

procedure init(X1,Y1,side1:integer);

procedure show;

procedure hide;

procedure shift(X1,Y1:integer);

procedure explode(Step:integer);

end;

{-----------------------------------------}

IMPLEMENTATION

procedure location.init(X1,Y1:integer);

begin

x:=X1;

y:=Y1;

end; {location.init}

function location.getX:integer;

begin

getX:=x;

end; {location.getX}

function location.getY:integer;

begin

getY:=y;

end; {location.getY}

procedure point.init(X1,Y1:integer);

begin

location.init(X1,Y1);

end; {point.init}

procedure point.show;

begin

visible:=true;

putpixel(x,y,getcolor);

end; {point.show}

procedure point.hide;

begin

visible:=false;

putpixel(x,y,getbkcolor);

end; {point.hide}

procedure point.shift(X1,Y1:integer);

begin

hide;

init(X1,Y1);

show;

end; {point.shift}

procedure square.init(X1,Y1,side1:integer);

begin

side:=side1;

point.init(X1,Y1);

end; {square.init}

procedure square.show;

begin

visible:=true;

rectangle(X-side div 2, X- side div 2, X+side div 2, Y+ side div 2);

end; {sguare.show}

procedure square.hide;

var temp:word;

begin

temp :=getcolor;

setcolor(getbkcolor);

show;

visible:=false;

Setcolor(temp);

end; {sguare.hide}

procedure square.shift(X1,Y1:integer);

begin

hide;

X:=X1;

Y:=Y1;

show;

end; {sguare.shift}

procedure square.explode(step:integer);

begin

hide;

inc(side,step);

show;

end;

end.

Чтобы использовать эти типы объектов и методы, в своей программе достаточно определить экземпляры типа Point и Square:

program ex1_OOP;

uses crt,graph,obj1_OOP;

var gm,gd :integer;

XP :point;

XS :square;

I :word;

Begin

gd:=detect;

InitGraph(gd,gm,'C:\BP\BGI');

if GraphResult<>GrOk then Halt(1);

with XP do

begin

init(100,100);

show;

readln;

shift(200,200);

readln;

hide;

end;

with XS do begin

init(100,100,50);

show;

readln;

shift(200,200);

readln;

for i:= 1 to 20 do

begin

explode(10);

delay(200);

end;

readln;

hide;

end;

closeGraph;

End.

В этом примере инициализируется точка, затем она показывается на экране, перемещается в новое место и прячется. Затем инициализируется квадрат, показывается на экране, в 20 раз увеличивает свои линейные размеры на 5 точек и стирается.

Когда родительский тип определен, наследуемые правила могут быть заменены (а могут и использоваться). Для замены унаследованного правила просто определите новое правило с тем же именем, как и унаследованное, но с другим телом и (при необходимости) с другим набором параметров. Логика компилятора в решении вызовов методов такова: компилятор сначала ищет метод с таким именем, определенный в пределах типа объекта. Тип Square определяет методы с именами Init, Show, Hide, Shift и Explode. Если тип Square должен вызвать один из этих методов, компилятор заменит этот вызов адресом одного из собственных методов объекта Square.

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

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

Unit obj2_OOP;

Interface

Uses Graph, obj1_OOP;

Type PaintSquare = Object(Square)

SquareColor: Word;

Procedure Init(X1,Y1,Side1,Color:Integer);

Procedure Show;

Procedure Hide;

Procedure Shift(X1,Y1:Integer);

Procedure Explode(Step:Integer);

End;

Implementation

Procedure PaintSquare.Init(X1,Y1,Side1,Color:Integer);

Begin

Square.Init(X1,Y1,Side1);

SquareColor :=Color;

End;

Procedure PaintSquare.Show;

Var Temp : Word;

Begin

Square.Show;

Temp:=GetColor;

SetFillStyle(SolidFill, SquareColor);

FloodFill(X,Y,Temp);

SetColor(Temp);

End;

Procedure PaintSquare.Hide;

Begin

SetFillStyle(SolidFill,GetBkColor);

FloodFill(X,Y,GetBkColor);

Square.Hide;

End;

Procedure PaintSquare.Shift(X1,Y1 : Integer);

Begin

Hide;

Init(X1,Y1,Side,SquareColor);

Show;

End;

Procedure PaintSquare.Explode(Step : Integer);

Begin

Hide;

Inc(Side,Step);

Init(X,Y,Side,SquareColor);

Show;

End;

End.

Используется модуль аналогично предыдущему. В следующем примере инициализируется закрашенный квадрат, затем он показывается на экране, перемещается на новое место и, наконец в 20 раз увеличивает линейные размеры на 5 точек, а затем возвращается в исходное состояние путем последовательного уменьшения.

Program EX2_OOP;

Uses Crt, Graph, obj2_OOP;

var gd,gm : integer;

XPS : PaintSquare;

I : Word;

begin

gd:=Detect;

InitGraph(gd,gm,'C:\BP\BGI');

If graphResult<>GrOk then Halt(1);

With XPS do

Begin

Init(100,100,50,14);

Show;

Readln;

Shift(200,200);

Readln;

For i:=1 to 20 do Begin

Explode(5);

Delay(200);

End;

Readln;

For i:=1 to 20 do Begin

Explode(-5);

Delay(200);

End;

Readln;

CloseGraph;

End;

End.