You are on page 1of 12

Chapter 5 The Sender

parameter and
substitution

Problem solutions
Problem 5.1 Study Chapter 5

Identify the appropriate example(s) or section(s) of the chapter to illustrate each comment
made in the summary above.

Problem 5.2 RTTI

Consider the following program:

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 1
Figure 7 Start up screen for
problem 6.1

Figure 8 Objects on the user


interface

The event handlers for all the objects on the user interface are routed through the following
event handler:

23 procedure TfrmSender.GeneralClick(Sender: TObject);


24 var
25 Class1, Class2: TClass;
26 ClassStr: string;
27 begin
28 Class1 := Sender.ClassType;
29 Class2 := Class1.ClassParent;
30 while Class2 <> nil do
31 begin
32 ClassStr := Class1.ClassName + ' derived from ' +
33 Class2.ClassName;
34 lstClasses.Items.Add(ClassStr);
35 Class1 := Class1.ClassParent;
36 Class2 := Class1.ClassParent;
37 end;
38 lstClasses.Items.Add('');
39 end; // procedure TfrmSender.GeneralClick

40 end. // end SenderU

Solutions Chapter 5, Page 2 Object orientation with Delphi (all rights reserved)
a) Explain how this event handler works and what it does, referring to the principles
covered in chapter 5.

Class1 and Class2 are of type TClass. In contrast to the other types we have seen, which
hold a reference to an object of a particular class, TClass holds a reference to a class. This
is sometimes called a class-reference type or a metaclass. This allows methods to be
applied to a class, whereas other types provide references to an object. We’ve seen
something like this before in the for of a constructor, which operates on the class and not
on a specific object.
When calling a constructor we refer to a specific class. But at other times we want a
variable that refers to a class, and this is where a class-reference type can be useful. The
Delphi type TClass is defined as a reference to a class of type TObject. All objects are
derived from TObject, and so TClass can also hold a reference to any descendant of
TObject.
The ClassType method (line 28 above) returns a reference an object’s class and the
ClassParent method returns a reference to the parent class of an object or class reference.
For TObject, ClassParent returns nil, a characteristic we use to terminate the while loop
(line 30). Avoid using ClassParent in application code.
So each iteration of the while loop displays a particular object’s class and its parent
class and then navigates one level up the class hierarchy by using the ClassParent
method. Iterations continue until the top of the hierarchy.

b) Draw the UML class diagram for all the classes in this program on the basis of this
program’s operation.

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 3
Class structure for the user interface of problem 6.1

Problem 5.3 Centralised control of several traffic lights

This questions develops out of the concepts and program covered in the earlier properties-
based traffic light problem for chapter 4. For this problem, create a master control panel
(figures 9 & 10) that controls three individual traffic light displays.

Solutions Chapter 5, Page 4 Object orientation with Delphi (all rights reserved)
Figure 9 The traffic light
control panel with the three
independent displays

Figure 10 The traffic light control panel

This control panel provides independent control of three different traffic lights. Each traffic
light can be set to automatic or manual via a CheckBox. When the CheckBox is checked the
associated traffic light runs automatically (4 cycles red, 3 cycles green, 1 cycle yellow). When
the CheckBox is unchecked, the Step button is enabled. Each click on the Step button moves
the associated traffic light, independently of the other two, to the next colour in the
sequence. The third control for each light, a SpinEdit, gives the cycle length in tenths of a
second. So if a SpinEdit is set to 8, the light it controls spend 3.2 seconds on red, 2.4s on
green and 0.8s on yellow. Any change of value in a SpinEdit takes effect from the next
colour change.
Code this program, incorporating the OO principles covered so far in this module as
appropriate. Include simple UML documentation. There are different ways to tackle this
problem. Less experienced programmers might find the following steps useful:

1. Write a simple low-level description / algorithm for each of the following cases:
a. Enable a traffic light for automatic operation by checking a CheckBox.
b. Disable automatic stepping and step manually through the sequence by clicking on a
button.

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 5
c. Check a CheckBox for automatic operation and then change the cycle time.
2. From these descriptions, decide what classes are needed and how they should be related.
3. Based on the classes in the class diagram, draw a sequence diagram for each of the cases
above.
4. Implement each case in turn.

It’s probably easier not to solve the whole problem in one go. Instead, you may decide to
start with just the controller and a single traffic light and to concentrate on switching that
light’s automatic operation on and off correctly. You would then have a choice. You could
get three lights controlled independently. Then you could get the manual control working
for one light and extend it to three, and finally program the adjustable cycle for one and
then extend it to all three. Alternatively, you could stick with a single light and get the
manual stepping to work, followed by the adjustable cycle, and then finally expand that to
the independent control of first two lights and then three lights.
Whichever approach you take will involve some iteration and each step forward is likely
to involve changes to some of the code already written, and possibly some changes to the
designs under points 1, 2 or 3 above.

5. Once the program is written, tested and working, use Visio to draw a UML class diagram
showing the master control panel, the traffic light display(s), the traffic light class(es) and
any other significant classes and the relationships between these classes, and sequence
diagrams showing the operation for each of the cases.

6. Prepare a brief description (½ to 1 types page) of how the program works and identify
the OO principles you have included.

Discussion

There are many different ways to write this program, and the version below (figures 11 and
12) uses only concepts that have already been introduced. With the knowledge gained from
subsequent chapters, one might well decide to structure this differently.

Solutions Chapter 5, Page 6 Object orientation with Delphi (all rights reserved)
Figure 11 A possible class diagram for the Traffic Controller

In the sequence diagram for enabling automatic operation (figure 12), the timer runs
repetitively. In order to keep sequence diagrams uncluttered it is often better to minimise
any display of control aspects. However, when necessary, the UML standard for repetition
involves drawing a ‘recurrence’ box around the affected messages. The drawing tool used
here does not offer the recurrence box, and so the repeated messages are shown in fig 12
with an asterisk, which is another convention used for repetition.

Figure 12 Enabling automatic operation

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 7
Controlling the lights manually involves disabling the automatic operation and then
stepping manually for each change.

One can approach the creation of the software in two ways. One can start a new project
and add the existing units before modifying them and introducing the VFI. Otherwise one
can start with the previous example, switch the main form and then VFI from the
previous one.

This problem covers adding directly mapped properties to RAD forms, VFI, replacing
parameters with method calls, communication between objects, and using Sender type
substitution.

unit MasterControlU;

{ Developed from the single traffic light display.


This version introduces a master controller for three lights.
Uses the previous display as a VFI template (TemplateU).
Derives three (empty) displays from TemplateU.
The Master Controller switches individual displays between
automatic and manual operation and changes cycle lengths.
Each individual controller has its own cycle unit length,
set in tenths of a second:
Yellow = 1 cycle unit
Green = 3 cycle units
Red = 4 cycle units
}

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, StdCtrls, Spin;

type
TfrmMasterControl = class(TForm)
chkLight1: TCheckBox;
btnStepLight1: TButton;
sedCycle1: TSpinEdit;
{ Same for the 2nd and 3rd controls }
procedure FormShow(Sender: TObject);
procedure chkLight1Click(Sender: TObject);
procedure btnStepLight1Click(Sender: TObject);
procedure sedCycle1Change(Sender: TObject);
{ same for the 2nd and 3rd controls }
end;

var
frmMasterControl: TfrmMasterControl;

Solutions Chapter 5, Page 8 Object orientation with Delphi (all rights reserved)
implementation

uses Controller1U, Controller2U, Controller3U;

{$R *.dfm}

procedure TfrmMasterControl.FormShow(Sender: TObject);


begin
frmTrafficLight1.Show;
frmTrafficLight2.Show;
frmTrafficLight3.Show;
end; // end procedure TfrmMasterControl.FormShow

procedure TfrmMasterControl.chkLight1Click(Sender: TObject);


begin
frmTrafficLight1.Auto := chkLight1.Checked;
btnStepLight1.Enabled := not chkLight1.Checked;
end; // end procedure TfrmMasterControl.chkLight1Click

procedure TfrmMasterControl.btnStepLight1Click(Sender: TObject);


begin
frmTrafficLight1.StepToNext;
end; // end procedure TfrmMasterControl.btnStepLight1Click

procedure TfrmMasterControl.sedCycle1Change(Sender: TObject);


begin
frmTrafficLight1.CycleLength := sedCycle1.Value;
end; // end procedure TfrmMasterControl.sedCycle1Change

{ Same for the 2nd and 3rd controls }

end. // end unit MasterControlU

unit TemplateU;

{ The VFI template for the actual traffic light displays.


All the code is specified here.
}

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, StdCtrls,
TrafficLightU;

type
TfrmTrafficLight = class(TForm)
{Standard RAD declarations}
private
MyTrafficLight: TTrafficLight;
FPeriod: integer;
FState: string;
FStopLight: TColor;

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 9
FGoLight: TColor;
FCautionLight: TColor;
FAuto: boolean;
FCycleLength: integer;
procedure UpDateDisplay;
procedure SetAuto(const Value: boolean);
public
property Period: integer read FPeriod write FPeriod;
property State: string read FState write FState;
property StopLight: TColor read FStopLight write FStopLight;
property CautionLight: TColor read FCautionLight
write FCautionLight;
property GoLight: TColor read FGoLight write FGoLight;
property Auto: boolean read FAuto write SetAuto;
property CycleLength: integer read FCycleLength
write FCycleLength;
procedure StepToNext;
end;

var
frmTrafficLight: TfrmTrafficLight;

implementation

{$R *.dfm}

procedure TfrmTrafficLight.tmrTrafficLightTimer(Sender: TObject);


begin
StepToNext;
end; // end procedure TfrmTrafficLight.tmrTrafficLightTimer

procedure TfrmTrafficLight.FormShow(Sender: TObject);


begin
CycleLength := 10; // default value

MyTrafficLight := TTrafficLight.Create;
State := 'Caution';
StepToNext; // goes to red
Auto := False; // start in manual
end; // end procedure TfrmTrafficLight.FormShow

procedure TfrmTrafficLight.StepToNext;
begin
MyTrafficLight.NextState(Self);
UpDateDisplay;
end; // end procedure TfrmTrafficLight.StepToNext

procedure TfrmTrafficLight.UpDateDisplay;
begin
tmrTrafficLight.Interval := Period;
lblTrafficLight.Caption := State;
shpRed.Brush.Color := StopLight;
shpYellow.Brush.Color := CautionLight;

Solutions Chapter 5, Page 10 Object orientation with Delphi (all rights reserved)
shpGreen.Brush.Color := GoLight;
end; // end procedure TfrmTrafficLight.UpDateDisplay

procedure TfrmTrafficLight.SetAutoconst Value: boolean);


begin
tmrTrafficLight.Enabled := Value;
FAuto := Value; // not really needed, never read
end; // end procedure TfrmTrafficLight.SetAuto

end. // end unit LightControlU

unit Controller1U;

{ All three displays similar to this.


To support substitution (TrafficLightU), all code and data in
parent.
Also, no need for any extension or specialisation here.
}

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics,
Controls, Forms, Dialogs, ExtCtrls, StdCtrls, TemplateU;

type
TfrmTrafficLight1 = class(TfrmTrafficLight);

var
frmTrafficLight1: TfrmTrafficLight1;

implementation

{$R *.dfm}

end.

unit TrafficLightU;

{ Model of the application / domain object }

interface

uses Forms;

type
TTrafficLight = class (TObject)
public
procedure NextState (AClient: TForm);
end;

implementation

The Sender parameter and substitution (26 Jun 2006) Chapter 5, Page 11
uses TemplateU,
Graphics; // for TColor

{ TTrafficLight }

procedure TTrafficLight.NextState (AClient: TForm);


begin
if (AClient is TfrmTrafficLight) then // similar to use of Sender
with TfrmTrafficLight(AClient) do // - typecasting and 'with'
if State = 'Stop' then // all references to client form
begin
Period := 300 * CycleLength; // update values on client form
State := 'Go';
StopLight := clBlack;
GoLight := clGreen;
end
else if State = 'Go' then
begin
Period := 100 * CycleLength;
State := 'Caution';
GoLight := clBlack;
CautionLight := clYellow;
end
else
begin
Period := 400 * CycleLength;
State := 'Stop';
CautionLight := clBlack;
StopLight := clRed;
end;
end; // end procedure TTrafficLight.NextState

end. // end unit TrafficLightU

Relevant OO principles that one can discuss:


1. Inheritance for the user interface objects (ie, VFI).
2. An alternative to VFI is to instantiate three traffic light objects from the same class by
using Application.CreateForm (TfrmTrafficLight, frmTrafficLight1) (etc) in either the
project file or one of the unit files.
3. Separation of concerns: different classes for the major different responsibilities such as
overall control, detailed control, display.
4. Additional encapsulation / information hiding issues like properties / access methods
and visibility restricted as much as possible.

Solutions Chapter 5, Page 12 Object orientation with Delphi (all rights reserved)

You might also like