Е. К. Пугачев Объектно-ориентированное программирование Под общей редакцией Ивановой Г. С. Рекомендовано Министерством общего и профессионального образования Российской Федерации в качестве учебник
Вид материала | Учебник |
- Е. Л. Григоренко психогенетика под редакцией И. В. Равич-Щербо Рекомендовано Министерством, 27103.82kb.
- Г. В. Плеханова И. Н. Смирнов, В. Ф. Титов философия издание 2-е, исправленное и дополненное, 4810.28kb.
- К. Э. Фабри Основы зоопсихологии 3-е издание Рекомендовано Министерством общего и профессионального, 5154.41kb.
- Е. А. Климов введение в психологию труда рекомендовано Министерством общего и профессионального, 4594.17kb.
- Н. Ф. Самсонова Рекомендовано Министерством общего и профессионального образования, 6152.94kb.
- Ю. Г. Волков И. В. Мостовая социология под редакцией проф. В. И. Добренькова Рекомендовано, 6915.59kb.
- Е. Ф. Жукова Рекомендовано Министерством общего и профессионального образования Российской, 6286.83kb.
- О. А. Кривцун эстетика Рекомендовано Министерством общего и профессионального образования, 6381.8kb.
- В. И. Рудой классическая буддийская философия рекомендовано Министерством, общего, 6771.74kb.
- В. И. Ильинича Рекомендовано Министерством общего и профессионального Образования Российской, 6751.75kb.
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.