Материал: Мансуров. Основы программирования в среде Lazarus. 2010

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

5.5. Полиморфизм

____________________________________________________________________

begin

Result:= inherited GetData + ', кафедра ' + kafedra; end;

var

Student: TStudent; Professor: TProfessor; fname: string;

begin

Student:= TStudent.Create; Professor:= TProfessor.Create; Student.name:= 'Виталий'; Student.fam:= 'Петров'; Student.group:= '"ПОВТАС-1/09"'; fname:= Student.GetData;

writeln(UTF8ToConsole('Это: ' + fname));

Professor.name:= 'Иван';

Professor.fam:= 'Иванов';

Professor.kafedra:= '"Программирование"';

fname:= Professor.GetData;

writeln(UTF8ToConsole('Это: ' + fname)); writeln(UTF8ToConsole('Нажмите любую клавишу'));

readkey;

Student.Free;

Professor.Free;

end.

Кроме виртуальных методов могут быть объявлены и так называемые ди-

намические методы. Они объявляются с помощью ключевого слова dynamic.

446

Глава 5 Основы объектно-ориентированного программирования

____________________________________________________________________

А в классах наследниках все того же ключевого слова override. С точки зре-

ния наследования, методы этих двух видов одинаковы: они могут быть пере-

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

(ТВМ), а для динамических методов таблица динамических методов (ТДМ).

В ТВМ хранятся адреса всех виртуальных методов класса, включая и ро-

дительских классов, даже если они не перекрыты в данном классе. Поэтому вы-

зовы виртуальных методов происходят достаточно быстро, однако ТВМ требу-

ет больше памяти.

С другой стороны, каждому динамическому методу присваивается уни-

кальный индекс. В ТДМ хранятся индексы и адреса только тех динамических методов, которые описаны в данном классе, поэтому ТДМ занимает меньше памяти. При вызове динамического метода, происходит поиск в ТДМ данного класса. Если поиск не дал результатов, поиск продолжается в ТДМ всех клас-

сов-родителей в порядке иерархии. Чем больше глубина иерархии классов, тем медленнее будут работать вызовы динамических методов.

Чтобы реализовать динамические методы для нашего примера, достаточно заменить слово virtual, на dynamic.

Посмотрим теперь на код метода Status в родительском классе. Факти-

чески в этом методе ничего не делается, функция возвращает пустую строку. В

таких случаях удобнее объявить метод как абстрактный с помощью ключевого слова abstract. Реализация метода, который объявлен как абстрактный, в

данном классе не производится, но обязательно должен быть переопределен в дочерних классах. Обратите внимание, только виртуальные методы могут быть объявлены абстрактными. Для нашего примера чтобы объявить абстрактный метод добавьте в классе THuman в объявление метода Status после слова virtual через точку с запятой ключевое слово abstract и удалите код реа-

лизации метода.

447

5.5. Полиморфизм

____________________________________________________________________

5.5.3 Конструкторы и деструкторы.

Для создания объектов мы применяли метод Create. Это так называемый конструктор, т.е. специальный метод класса, который предназначен для выде-

ления памяти и размещения в памяти экземпляра класса. Кроме того, в задачу конструктора входит инициализация значений полей экземпляра класса. Стан-

дартный конструктор устанавливает все данные нового экземпляра класса в ноль. В результате все числовые поля и поля порядкового типа приобретают нулевые значения, строковые поля становятся пустыми, а поля, содержащие указатели и объекты получают значение nil. Под стандартным конструктором имеется в виду конструктор, унаследованный классом от класса TObject.

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

ется использование нескольких конструкторов. Желательно, чтобы все конст-

рукторы имели стандартное имя Create. Это позволяет переопределять конст-

рукторы, включая и стандартный конструктор, для выполнения каких-либо по-

лезных действий. Описание конструктора производится с помощью ключевого слова constructor. Давайте в последнем примере предыдущего раздела в класс THuman добавим конструктор. Код программы будет следующим:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses

Classes, SysUtils; type

448

Глава 5 Основы объектно-ориентированного программирования

____________________________________________________________________

{ THuman }

THuman = class private

Fname: string;

Ffam: string;

procedure Setname(const AValue: string); procedure Setfam(const AValue: string);

public

property name: string read Fname write Setname; property fam: string read Ffam write Setfam; constructor Create; // конструктор

function GetData: string;

function Status: string; virtual; abstract; end;

implementation

{ THuman }

constructor THuman.Create; // реализация конструктора begin

Fname:= 'Андрей';

Ffam:= 'Аршавин'; end;

procedure THuman.Setname(const AValue: string); begin

if Fname=AValue then exit;

449

5.5. Полиморфизм

____________________________________________________________________

Fname:=AValue;

end;

procedure THuman.Setfam(const AValue: string); begin

if Ffam=AValue then exit; Ffam:=AValue;

end;

function THuman.GetData: string; begin

Result:= name + ' ' + fam + Status; end;

end.

program project1; {$mode objfpc}{$H+} uses

CRT, FileUtil, Unit1; type

TStudent = class(THuman) private

group: string; public

function GetData: string; function Status: string; override;

end;

450

Смотрите также:

1 — пак
11 Горм +
113
14
1433
1511
1632
199
204
2714