Ex 5.1 step 6 An alternative typecasting operatorStep 5 is the main focus of this example. But there are still two points to make before completing the example. The first is that the as operator is part of Delphi but was not part of the original Pascal. It (as) has the advantage of doing strict error-checking and throwing an exception if one tries to typecast wrongly. Originally Pascal typecast through brackets, and Delphi recognises this too. So we can change line 30 of the program above to:
The bracket notation looks a bit like a subroutine call and does not perform any error checking. So, although it is slightly less efficient, many programmers prefer the as operator for typecasting since it is more robust and easier to read.
28 procedure TfrmSender.GeneralClick(Sender: TObject) ; 29 begin 30 if Sender is TComponent then pnlReport.Caption := 'You clicked on ' + TComponent(Sender).Name 31 end;
Ex 5.1 step 7 The equality operatorWe have used the Sender parameter with the is and as class operators. The first, is, determines the class of an object and often forms the conditional part of an If statement. So in step 6 above we used is to determine what class Sender represents.
However, if we want to find out which specific component or object Sender represents we can use the equality operator =. For example, lets assume that the Forms color should be aqua if spdFive is clicked and green if any other component is clicked. We can do this as follows (lines 3336):
procedure TfrmSender.GeneralClick(Sender: TObject) ; begin if Sender is TComponent then pnlReport.Caption := 'You clicked on ' + (Sender as TComponent).Name; if Sender = spdFive then Color := clAqua else Color := clGreen; end;
Example 5.1 SummaryThe crucial point of this example is to introduce the concept of substitution. The Sender parameter, which is part of every event, tells the event handler which component initiated the event. Many different components can initiate events and so the Sender parameter is of type TObject, the most general type of object that there is in Delphi.
The is and the = operators allow us to test whether Sender represents either a particular class or a particular object. To use Sender in a program we need to typecast it appropriately and we can use either as (with error checking) or () (without checking) for the typecasting.
In this example we saw that a property that is available to a TComponent object is also available to TSpeedButton, TForm and TPanel objects because all three descend from TComponent. Because of the inheritance hierarchy, a subtype inherits all the functionality of the supertype as a starting point, and so a subtype can take on the role of any of its ancestors.
However an ancestor, which is typically more restricted than the subtype, cannot take on all the roles of the subtype and trying to substitute an ancestor for a subtype will lead to a compile error.
Example 5.2 Run time type information (RTTI)As we have seen from the is and as operators we used in example 5.1, Delphi can determine aspects of the class structure of an object at run time. In Win32, each object is associated with its run time type information, usually abbreviated as RTTI. There is more to RTTI than just is and as, though these may be the most commonly used. For example, the ClassName method returns a string, the InheritsFrom method returns a Boolean, and ClassType and ClassParent both return a TClass variable. You can modify the previous program to illustrate these RTTI methods:
procedure TfrmSender.GeneralClick(Sender: TObject) ; begin lblInheritance.Caption := 'Class Name: ' + Sender.ClassName; pnlReport.Caption := 'TCustomControl descendant: ' + BoolToStr(Sender.InheritsFrom(TCustomControl), True) ; end;