Introducing (in this Chapter):
- Substitution
- The Sender parameter
- Typecasting
- Class and instance operators
- RTTI: run time type information
Introduction
An important consequence of an inheritances hierarchy is the concept of substitution, where an instance of a subclass object can substitute for a variable declared as any of its supertypes. In this brief chapter we introduce the concept of substitution by investigating the Sender parameter that is part of the parameter list of every event handler.Different events have different parameter lists but the first in the list for all events is Sender: TObject, which identifies the component that initiated the event. Identifying the event initiator is a useful idea, but not completely straightforward. The difficulty is that every parameter must have a type, and so Sender must be declared as a specific type. But what type should Sender be? Every component is different. As well see in the example that follows, Delphi uses the inheritance hierarchy to solve this problem.
Note: for a start you can read the "Understanding the Sender parameter in Delphi Event Handlers"
Example 5.1 The Sender parameter in event handlers
The example well use to illustrate the Sender parameter has six SpeedButtons, two panels, a label and a form. The goal of this program is to display an appropriate message in response to a click on any of these components. One way of doing this is to write ten event handlers, one for each component, each displaying the required message.But this leads to a lot of effort and, worse, the repeated code introduces many opportunities for future errors. What would be better would be to write just one procedure, to route all the OnClick events through this code, and then use the Sender parameter to generate a message identifying which component has been clicked.
Ex 5.1 step 1 The OnClick event handler, version 1
Well start with some simple code and then develop it into the complete program. Create an OnClick event handler for spdOne to display the value of spdOnes Caption and then test this first version of the program.28 procedure TfrmSender.spdOneClick(Sender: TObject) ;
29 begin
30 pnlReport.Caption := 'You clicked on ' + spdOne.Name;
31 end;
Ex 5.1 step 2 Using the Sender parameter
Now well modify this event handler to use the Sender parameter. One possibility is to change spdOne in the assignment statement to Sender (line 30 below):28 procedure TfrmSender.spdOneClick(Sender: TObject) ;If you try this youll see that it does not work. The compiler returns an Undeclared identifier error. Why is this? In the parameter list in the header of this OnClick event handler, and all other event handlers, Senders type is defined as TObject, the root class of the hierarchy, and not as TSpeedButton (line 28). The TObject class does not have a Name property, and so, when the compiler reaches Sender.Name in line 30, it generates an error.
29 begin
30 pnlReport.Caption := 'You clicked on ' + Sender.Name;
31 end;
Because Sender is a completely general parameter it is declared as type TObject. However, in this case we know that Sender is a TSpeedButton and so we must instruct Delphi to treat Sender as a TSpeedButton in other words we must typecast Sender as a TSpeedButton. There are different ways to do this. Here we use the as class operator as follows (line 31):
28 procedure TfrmSender.spdOneClick(Sender: TObject) ;This program compiles and works like the previous version, so we now seem to be using the Sender parameter correctly. We have seen the "as" typecasting operator in passing in example 2.1 step 2 line 17, and here we will look at it more closely. This typecasting informs Delphi that although Sender is declared in the parameter list as a TObject because it could be any one of a number of different classes, in this particular case Delphi must treat it as a TSpeedButton (line 31 above).
29 begin
30 pnlReport.Caption := 'You clicked on ' + (Sender as TSpeedButton).Name;
31 end;


