Конспект лекций по дисциплине «Высокоуровневые методы информатики и программирования» для студентов специальности 080801 «Прикладная информатика в экономике»

Вид материалаКонспект

Содержание


В результате использования механизма наследования отпадает необходимость заново описывать уже существующие в классе-родителе пол
Field identifier expected
Type =Object(
Program SymbOb
Cf,Cs, {цвет фона и символов} Col,Line:byte
Procedure MakeWin
Пример 2.19. Использование наследования (классы Окно и Символ)
Type Symb = Object(Win)
Procedure Print
Присваивание объектов
Var Winvar : Win
Var Winvar : ^Win
Winvar := Symbvar
Подобный материал:
1   ...   5   6   7   8   9   10   11   12   ...   25

2.2.Наследование


В первой главе сформулировано следующее определение.

Наследование - это такое соотношение между классами, когда один класс использует структурную или функциональную часть одного или нескольких других классов (соответственно простое и множественное наследование).

В Borland Pascal 7.0 реализовано простое наследования, при котором у класса может быть только один родитель, но сколько угодно потомков.

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

^ В результате использования механизма наследования отпадает необходимость заново описывать уже существующие в классе-родителе поля и методы. Требуется описать только те поля и методы, которых недостает в классе родителе.

Доступ к полям, описанным в классе-родителе, осуществляется также как к собственным. Поиск метода в иерархии классов выполняется следующим образом.

1. В первую очередь компилятор устанавливает тип объекта.

2. Далее он ищет метод в классе объекта и если находит, то подключает его.

3. Если метод в классе объекта не найден, то идет поиск в классе-родителе. В случае успеха вызывается метод родителя.

4. Если метод в классе-родителе не найден, то поиск продолжается в классах-предках до тех пор, пока вызванный метод не будет найден.

Если компилятор не обнаруживает метод, то он фиксирует ошибку компиляции номер 44 (^ Field identifier expected– «ожидается имя поля или метода класса»).

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

Структура описания класса-потомка:

^ Type <имя класса-потомка>=Object(<имя класса-родителя>)

<новые поля класса-потомка>

<новые методы класса-потомка>

End;

Примеры 2.2 и 2.3 иллюстрируют преимущества механизма наследования.

Пример 2.18. Разработка сложного класса без использования наследования (класс Символ)

Пусть описан класс Символ (Symb), который позволяет создавать окно и выводить символ в заданную позицию.

^ Program SymbOb;

Uses Crt;

Type

Symb = Object {класс Символ}

{Поля класса}

X1,Y1, {координаты верхнего левого угла окна}

X2,Y2, {координаты нижнего правого угла окна}

^ Cf,Cs, {цвет фона и символов}

Col,Line:byte; {позиция символа}

Sym:char; {символ}

{Методы класса}

Procedure Init(Xn1,Yn1,Xn2,Yn2,Cfn,Csn,Cl,Ln:byte;Sm:Char);

^ Procedure MakeWin; {создание окна}

Procedure Print; {вывод символа}

End;

Procedure Symb.Init;

Begin

X1:=Xn1; Y1:=Yn1; X2:=Xn2; Y2:=Yn2; Cf:=Cfn;

Cs:=Csn; Col:=Cl; Line:=Ln; Sym:=Sm;

End;

Procedure Symb.MakeWin;

Begin

Window(X1,Y1,X2,Y2); Textbackground(Cf); Clrscr

End;

Procedure Symb.Print;

Begin

TextColor(Cs); Gotoxy(Col,Line); Write(Sym)

End;

Var Symbvar : Symb; {объявление экземпляра класса}

Begin

Symbvar.Init(1,1,80,25,7,1,40,12,'A'); {инициализировать объект}

Symbvar.MakeWin; {нарисовать окно}

Symbvar.Print; {вывести символ}

Readkey;

End.

Если сравнить примеры 2.1 и 2.2, то можно заметить, что поля X1, Y1, X2, Y2, Cf и метод MakeWin совпадают. Следовательно, класс Symb можно наследовать от класса Win.

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

^ Пример 2.19. Использование наследования (классы Окно и Символ)

На рис. 2.1 представлена иерархия классов для рассматриваемого примера, в которой показано, что класс Символ наследуется от класса Окно. Справа для классов указаны используемые поля и методы, причем для класса-потомка указаны только те поля и методы, которые отсутствуют в родительском классе. Иерархия классов в данном случае простая и имеет всего два уровня, где Win считается классом первого уровня, а Symb - классом второго уровня.



Рис. 2.34. Иерархия классов примера 2.3

В примере 2.3 класс Symb объявлен как потомок класса Win.

Program WinSymbOb;

Uses Crt;

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .}

{ Описание класса Win и его методов из примера 2.1 }

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .}

^ Type

Symb = Object(Win) {класс-потомок «символ»}

{Новые поля}

Cs, {цвет символов}

Col,Line:byte; {позиция символа}

Sym:char; {символ}

{Новые методы}

Procedure Init(Xn1,Yn1,Xn2,Yn2,Cfn,Csn,Cl,Ln:byte;Sm:Char); {инициализация полей}

^ Procedure Print; {вывод символа}

End;

Procedure Symb.Init;

Begin

Win.Init(Xn1,Yn1,Xn2,Yn2,Cfn); {используем родительский метод}

Cs:=Csn; Col:=Cl; Line:=Ln; Sym:=Sm;

End;

Procedure Symb.Print;

Begin TextColor(Cs); Gotoxy(Col,Line); Write(Sym) End;

Var Symbvar : Symb; {объявление экземпляра класса}

Begin

with Symbvar do begin

Init(1,1,80,25,7,1,40,12,'A'); {инициалировать объект}

MakeWin; {изобразить окно}

Print {вывести символ}

end;

Readkey;

End.

Результаты работы программы примера 2.3 аналогичны результатам работы программы примера 2.2. Применение механизма наследования позволило повторно не описывать поля и методы ранее созданного класса, в результате чего заметно упростилась разработка класса Symb. Кроме этого, дополнительно появилась возможность использовать родительские методы GetSizeX и GetSizeY класса Win, также ранее определенные в классе Win.

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

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

<объект класса-родителя> := <объект класса-потомка>

Так для классов примера 2.3 возможно только присваивание полям объекта класса Win значений полей объекта класса Symb, например:

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . }

{. . . Описание классов Win и Symb из примера 2.3 . . . . . . .}

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . }

^ Var Winvar : Win; {объект-родитель}

Symbvar : Symb; {объект-потомок}

Begin Symbvar.Init(1,1,80,25,7,1,40,12,’A’);.

Winvar := Symbvar; {передать поля данных}

Winvar.MakeWin; {изобразить окно}

Write(Winvar.Cf); {на сером фоне будет выведено синим цветом число 7}

End.

Операция присваивания применима и к динамическим объектам, память под которые запрашивается из динамической области, например

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . }

{ . . . Описание классов Win и Symb из примера 2.3 . . . . . . . }

{. . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . }

^ Var Winvar : ^Win; {указатель на объект-родитель}

Symbvar : ^Symb; {указатель на объект-потомок}

Begin New(Symbvar); {выделить память под объект}

Symbvar^.Init(1,1,80,25,7,1,40,12,’A’);. {инициализировать}

^ Winvar := Symbvar; {передать указатель}

Winvar^ := Symbvar^; {передать содержимое}

Winvar^.MakeWin; {изобразить окно}

Write(Winvar^.Cf); {вывести символ}

Dispose(Symvar); {освободить память}

End.

Более подробно применение динамических объектов и объектов с динамическими полями рассмотрено в разделе 2.4.