Reputation: 579
I've encountered some code that's new to me...
I've never really seen a type declaration of a procedure of object, and I just don't see the point. Why couldn't the developer simply keep a field of type Boolean?
interface
type
TFinishedCaptureEvent = procedure(AFinished: Boolean) of object;
TFrameCard = class(TFrame)
...
private
FOnFinishedCapture: TFinishedCaptureEvent;
procedure DoUpdateMessage(AMessageType: TMessageType);
public
property OnFinishedCapture: TFinishedCaptureEvent read FOnFinishedCapture write FOnFinishedCapture;
end;
implementation
...
procedure TFrameCard.DoUpdateMessage(AMessageType: TMessageType);
begin
if Assigned(FOnFinishedCapture) then
FOnFinishedCapture(False);
...
end;
end.
Upvotes: 12
Views: 22064
Reputation: 84550
Let's break this down into two parts to be easier to understand. First, procedure(AFinished: Boolean)
isn't a boolean
variable, it's a reference to a procedure that takes a boolean as a parameter. It's basically a procedure header, except without the procedure name because this is just a type definition. Any procedure that matches this signature can be assigned to this variable.
The of object
part means that this isn't just a procedure reference, but a method reference; it has to belong to an object. The compiler needs to know the difference so that it can store the self
pointer for the object together with the procedure pointer so it can be invoked properly, as the other posters have pointed out.
Basically, this is declaring a new event handler, and it's a pretty common pattern in Delphi. It's the same thing that the VCL does all over the place. When you create a button and assign an OnClick
handler, it has to be a procedure (Sender: TObject) of object;
. Your form gives the button a method reference referring to itself and the event handler procedure, and then the button uses that information to invoke the handler on the form when someone clicks it.
This code is doing the same thing. It's providing a way for some external object to be notified when DoUpdateMessage runs, using the standard Delphi idiom for event notification.
Upvotes: 22
Reputation: 10582
A procedure of object
is a procedure reference for procedures contained in class instances. When calling procedures that are members of a class, the implict Self
reference must be passed with the other parameters. Using procedure of object
tells the compiler to store the Self
reference with the procedure address inside the procedure reference, so that when the procedure is called via the procedure reference, the Self
reference will be automatically passed.
In the code snippet you provided, TFinishedCaptureEvent
is defined as a procedure of object, meaning that any variables created of its type will contain 2 values: the Self
value and the procedure address. When this variable is assigned to, in particular when the assignment is inside a class, the compiler will automatically set the Self value inside this variable to the instance of the class that contains the procedure being assigned to the variable. When the variable is called (FOnFinishedCapture(False)
), the compiler automatically passes the correct Self
value back to the procedure that was assigned to this variable.
Upvotes: 14
Reputation: 108810
I don't understand how you relate this to a field of boolean.
But TFinishedCaptureEvent = procedure(AFinished: Boolean) of object
declares a delegate/method pointer type, which is used for events. It's a record
which contains a self
pointer and a function pointer. When you call the delegate, the function is called with the self
passed as a parameter to the function.
Upvotes: 4