Мы уже говорили о процедурном типе. Переменная процедурного типа – это указатель на адрес процедуры или функции. Если же мы хотим сделать ссылку не просто на процедуру или функцию, а на метод объекта, то мы должны добавить ключевое словосочетание of object, записанное после прототипа процедуры или функции:
type TMethod = procedure of object; TNotifyEvent = procedure(Sender: TObject) of object; |
Переменная такого типа называется указателем на метод (method pointer). Она занимает в памяти 8 байт и хранит одновременно ссылку на объект и адрес его метода (получается, на самом деле 2 указателя). Например:
type TNotifyEvent = procedure(Sender: TObject) of object; TMainForm = class(TForm) procedure ButtonClick(Sender: TObject); ... end;var MainForm: TMainForm; OnClick: TNotifyEvent |
Тогда можно сделать следующую привязку:
OnClick := MainForm.ButtonClick; |
Используя переменные типа указателя на метод можно описывать события. Рассмотрим пример с использованием ранее описанного класса TFigure.
Type TFigure = class private FOnDraw: TNotifyEvent; public property OnDraw: TNotifyEvent read FOnDraw write FOnDraw; end; |
и в методе Draw:
procedure TFigure.Draw;begin ... //рисуем фигурку if Assigned(FOnDraw) then FOnDraw(Self); //уведомление о рисовании фигурки end;end; |
Обратите внимание, что вызов метода через указатель происходит лишь в том случае, если указатель не равен nil. Эта проверка выполняется с помощью стандартной функции Assigned, которая возвращает True, если ее аргумент является связанным указателем.
Описанный выше механизм называется делегированием, поскольку он позволяет передать часть работы другому объекту, например, сосредоточить в одном объекте обработку событий, возникающих в других объектах. Это избавляет программиста от необходимости порождать многочисленные классы-наследники и перекрывать в них виртуальные методы. Делегирование широко применяется в среде Delphi. Например, все компоненты делегируют обработку своих событий той форме, в которую они помещены.