Динамические методы

Одноимённые методы

Ещё раз посмотрим на различные способы замены методов базового класса-предка на одноимённый метод в классе-потомке.

Статическое замещение методов

В классе потомке объявляется метод с тем же именем и набором формальных параметров.

Метод класса потомка перекрывается одноимённым методом в классе-предке. Из класса-потомка обратиться к методу класса-предка невозможно.

Например:

type

TMyClass1=class
procedure pr1;
end;

TMyClass2=class(TMyClass1)
procedure pr1;
end;

var
Form1: TForm1;

implementation
{$R *.dfm}

procedure TMyClass1.pr1;
begin
showMessage(‘TMyClass1.pr1’);
end;

procedure TMyClass2.pr1;
begin
showMessage(‘TMyClass2.pr1’);
end;

procedure TForm1.Button1Click(Sender: TObject);
var vPr1:TMyClass1;
begin
vPr1:=TMyClass1.Create;
vPr1.pr1;
end;

Динамические методы

procedure TForm1.Button2Click(Sender: TObject);
var vPr2:TMyClass2;
begin
vPr2:=TMyClass2.Create;
vPr2.pr1;
end;

end.

Динамические методы

Никаким образом из переменной vPr2 вызвать процедуру, принадлежащую классу TmyClass1, невозможно.

Динамическое замещение методов

Такой способ позволяет обратиться как к методу родителя, так и к методу класса-последователя.

type

TMyClass1=class
procedure pr1; virtual;
end;

TMyClass2=class(TMyClass1)
procedure pr1; override;
end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TMyClass1.pr1;
begin
showMessage(‘TMyClass1.pr1’);
end;

procedure TMyClass2.pr1;
begin
showMessage(‘TMyClass2.pr1’);
end;

procedure TForm1.Button1Click(Sender: TObject);
var vPr1:TMyClass1;
begin
vPr1:=TMyClass1.Create;
vPr1.pr1;
FreeAndNil(vPr1);
vPr1:=TMyClass2.Create;
vPr1.pr1;
FreeAndNil(vPr1);
end;

end.

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

Таким образом сохраняется доступ как к методу класса-предка, так и к одноимённому методу класса-последователя.

Одноимённые методы.

Существует ещё один способ использовать одноимённые методы.

Хотя имя всех методов одно и то же, но у каждого должен быть свой уникальный набор параметров. Причём методы могут располагаться в одном и том же классе.

Перекрываемые методы должны иметь ключевое слово overload.

Кроме того, чтобы каждый раз не выводилось сообщение о том, что метод перекрывается, необходимо использовать сочетание ключевых слов reintroduce; overload; (именно в такой последовательности).

type

TMyClass1=class
procedure pr1;
end;

TMyClass2=class(TMyClass1)
procedure pr1(s:string); reintroduce; overload;
procedure pr1(s1,s2:string); reintroduce; overload;
end;

var

Form1: TForm1;

implementation

{$R *.dfm}

procedure TMyClass1.pr1;
begin
showMessage(‘TMyClass1.pr1’);
end;

procedure TMyClass2.pr1(s:string);
begin
showMessage(‘TMyClass2.pr1(s:string) ‘+s);
end;

procedure TMyClass2.pr1(s1,s2:string);
begin
showMessage(‘TMyClass2.pr1(s1,s2:string) ‘+s1+’ ‘+s2);
end;

procedure TForm1.Button1Click(Sender: TObject);
var vPr1:TMyClass1;
begin
vPr1:=TMyClass1.Create;
vPr1.pr1;
FreeAndNil(vPr1);
end;

Динамические методы

procedure TForm1.Button2Click(Sender: TObject);
var vPr2:TMyClass2;
begin
vPr2:=TMyClass2.Create;
vPr2.pr1;
vPr2.pr1(‘***’);
FreeAndNil(vPr2);
end;

Динамические методы
Динамические методы

procedure TForm1.Button3Click(Sender: TObject);
var vPr2:TMyClass2;
begin
vPr2:=TMyClass2.Create;
vPr2.pr1(‘***’,’###’);
FreeAndNil(vPr2);
end;

Динамические методы

end.

Динамическое перекрытие.

Динамическое перекрытие методов по синтаксису мало отличается от виртуальных методов. Вместо ключевого слова virtual указывается ключевое слово dynamic. Механизмы обращения к методам в обоих случаях идентичны.

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

То есть объём таблицы может быть достаточно большим, зато выбор метода осуществляется за один заход в таблицу. Это обеспечивает высокую скорость нахождения метода.

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

Встретив вызов динамического метода через переменную, тип которой задан через какой-либо класс, происходит поиск в динамической таблице этого класса.

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

* * *

Обновлено: 12.02.2021 — 19:33

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *