Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 400107.doc
Скачиваний:
5
Добавлен:
30.04.2022
Размер:
568.32 Кб
Скачать
      1. Статические и виртуальные методы. Полиморфизм Статические методы

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

Program Static;

Uses Crt;

Type

Location = Object {описываем объект Location}

X,Y:Byte; {переменные объекта X,Y}

Procedure Init; {методы объекта Init,Position}

Procedure Position(NewX,NewY:Byte); end;

{тексты методов объекта Location}

Procedure Location.Init;

Begin

X:=1;

Y:=1;

End;

Procedure Location.Position(NewX,NewY:Byte);

Begin

X:=NewX;

Y:=NewY;

End;

Type Ch = Object(Location) {объект Ch,базируется на объекте Location}

C:Char; {переменные объекта Ch: X,Y,C}

Procedure Init;

Procedure Show;

Procedure SetC(NewC:Char);

Procedure MoveTo(NewX,NewY:Byte);

End;

{Тексты методов объекта Ch}

procedure Ch.Init;

begin

Location.Init; C:=’A’;

End;

Procedure Ch.Show;

Begin

Write(C);

End;

Procedure Ch.SteC(NewC:Char);

Begin

C:=NewC;

End;

Procedure Ch.MoveTo(NewX,NewY:Byte);

Begin

X:=NewX;

Y:=NewY;

GotoXY(X,Y);

Show;

End;

Type St = Object (Ch) {объект St, базируется на объекте Ch}

S:string; {переменные объекта St:X,Y,C,S}

Procedure Init; Procedure Show;

Procedure SetS(NewS:String);

End;

{тексты методов объекта St}

procedure St.Init;

begin

Ch.Init; S:=’’;

End;

Procedure St.Show;

Begin

Write(S);

End;

Procedure St.SetS(NewS:String);

Begin

S:=NewS;

End;

{исполняемая часть программы}

var

S:St; {введем переменную S типа объект St}

Begin

ClrScr;

With S Do begin

Init; {1}

Sets(‘THIS IS A STRING’); {2}

MoveTo(10,10); {3}

End;

End.

Рассмотрим выполнение этой программы.

1) Строка {1}: Init выполняется St.Init

S:=’’;

Вызов Ch.Init C:=’A’; Вызов Location.Init

X:=1;

Y:=1;

2) Строка {2}: Sets(‘This is a string’); выполняется St.Sets

S:=’This is a string’;

3) Строка {3}: MoveTo(10,10);

В St нет метода MoveTo, поэтому бкдет выплнятся обращение к Cy.MoveTo (к методу объекта-предшественника).

3.1) X:=10;

Y:=10;

GotoXY(10,10);

3.2) вызов Show. Имеется два метода Show:Ch и St.Show.

Так как вызов Show выполняется из Ch.MoveTo, то будет вызван Ch.Show и на экране появится символ А. Связь между методами показана на рис. 2.1.

Location

Ch: Ch.MoveTo Ch.Show

St: St.Sets St.Show

Рис. 2.1. Путь вызова статических методов

Аналогичное можно видеть в программе, приведенной в п. 2. Объекты Point и Circle содержат методы Show, но они разные: высвечивание точки и круга. Метод Circle.MoveTo вызывает Show, подразумевается Circle.Show. Соответсвенно Point.MoveTo вызывает Point.Show.

Виртуальные методы. Полиморфизм

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

L ocation

C h: Ch.MoveTo Ch.Show

St: St.Sets St.Show

Рис. 2.2. Путь вызова виртуальных методов

Для придания методу атрибута виртуальности в его описании добавляется слово virtual. Если метод в объекте-предшественнике имеет атрибут virtual, то все методы с тем же именем во всех объектах наследниках тоже должны иметь атрибут virtual. Проиллюстрируем применение виртуальных методов на примерах. Программа, приведенная в п.2, принимает следующий вид. Благодаря использованию виртуальных методов Show и Hide нет необходимости в двух разновидностях метода MoveTo (для Circle и Point). Достаточно один метод MoveTo, вызов из него метода Show(Hide) означает вызов Point.Show или Circle.Show в зависмости от того, из какого объекта (Point или Circle) был вызван MoveTo.

Type Location = Object

X,Y:integer;

Procedure Init(InitX,InitY:integer);

Function GetX:integer;

Function GetY:integer;

End;

Point = Object(Location)

Visible:Boolean;

Constructor Init(InitX,InitY:integer): {конструктор}

Procedure Show; Virtual; {виртуальный метод}

Procedure Hide; Virtual; {виртуальный метод}

Function IsVisible:Boolean;

Procedure MoveTo(NewX,NewY:integer); Virtual;

End;

Circle = Object(Point)

Radius:integer;

Constructor Init(InitX,InitY:integer:Radius:integer);

Procedure Show; Virtual;

Procedure Hide; Virtual;

Procedure Expand(ExpandBy:integer);Virtual;

Procedure Contract(ContractBy:integer);Virtual;

End;

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

Var

Gd,Gm:integer;

P1:Point;

C1:Circle;

Begin

Gd:=Detect;

Graph.InitGraph(Gd,Gm,’’);

If GraphResult <> grOK then Halt(1);

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

P1.Init(50,60); {инициализировать точку}

P1.Show; {показать точку}

ReadLn; {для останова программы}

P1.MoveTo(100,100); {передвигать точку на новое место}

ReadLn;

C1.Init(50,60,30); {инициализировать окружность}

С1.Show; {показать окружность}

ReadLn;

P1.Hide; {погасить точку – центр окружности}

ReadLn;

With C1 Do begin

MoveTo(90,110); {передвигать окружность на новое место радиус прежний}

Expand(60); {изменить радиус окружности}

End;

ReadLn;

End.

Нетрудно видеть, что метод MoveTo( , ) передвигает на новое место то точку, то окружность. Это достигается вызовом из метода MoveTo разных методов Show и Hide.

Пример из п. 1. Принимает следующий вид:

Program Virt;

Uses Crt;

Type

Location = Object

X,Y:Byte;

Procedure Init;

Procedure Position(NewX,NewY:Byte);

End;

Procedure Location.Init;

Begin

X:=1;

Y:=1;

End;

Procedure Location.Position(NewX,NewY:Byte);

Begin

X:=NewX;

Y:=NewY;

End;

Type Ch = Object(Location)

C:Char;

Constructor Init; {конструктор}

Procedure Show;Virtual; {виртуальный метод}

Procedure SetC(NewC:Char);

Procedure MoveTo(NewX,NewY:Byte);

End;

Constructor Ch.Init;

begin

Location.Init;

C:=’A’;

End;

Procedure Ch.Show;

Begin

Write(C);

End;

Procedure Ch.SteC(NewC:Char);

Begin

C:=NewC;

End;

Procedure Ch.MoveTo(NewX,NewY:Byte);

Begin

X:=NewX;

Y:=NewY;

GotoXY(X,Y);

Show;

End;

Type St = Object (Ch)

S:string;

Constructor Init; {конструктор}

Procedure Show;Virtual; {виртуальный метод}

Procedure SetS(NewS:String);

End;

Constructor St.Init;

begin

Ch.Init;

S:=’’;

End;

Procedure St.Show;

Begin

Write(S);

End;

Procedure St.SetS(NewS:String);

Begin

S:=NewS;

End;

var

S:St; C:Ch;

Begin

ClrScr;

C.Init;

With S Do

begin

Init; {A}

Sets(‘THIS IS A STRING’); {B}

MoveTo(10,10); {C}

End;

End.

Рассмотрим подробнее выполнение этой программы.

1) C.Init означает запуск Ch.Init.

C:=’A’;

вызов Location.Init;

X:=1; Y:=1;

2) S.Init (строка {A}) означает запуск St.Init.

2.1) запуск конструктора;

2.2) S:=’’;

2.3) Вызов Ch.Init;

C:=’A’;

Вызов Location.Init;

X:=1;Y:=1;

3) S.Sets означает запуск St.Sets. S:=’This is a string’;

4) MoveTo нет в St, поэтому запускается Ch.MoveTo.

X:=10;

Y:=10;

GotoXY(10,10);

Вызов Show

Благодаря виртуальности вызывается St.Show и Write(S).

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