Delphi Programming

  1. Home
  2. Computing & Technology
  3. Delphi Programming

Indirection - Delphi OOP Part 8 - Chapter 18

By Zarko Gajic, About.com

Materials written by John Barrow. Modifications by Zarko Gajic

Back to Chapter 17

Introducing (in this Chapter):

  • Chaining and delegation in RAD classes.
  • Patterns for the Law of Demeter and for Delegation.

Example 8.3 Delegation

As we mentioned, the data fields of the intermediate class, TMuseumCount in example 8.2, are public. Isn’t it almost a golden rule of object orientation that data fields are private, and that if we want to access these data fields from outside the unit, we must use access methods of some form or other?

This is an important rule, and we’ll incorporate it in this example. We’ll declare the TCounter objects in TMuseumCount as private data fields. TMuseumCount will have public access methods and properties which will interact with the TCounter objects. In doing this, we will move from chaining to delegation (or forwarding). Delegation overcomes the encapsulation leakage that is inevitably part of chaining.

The intermediate object now encapsulates the subsidiary objects instead of exposing them, with similar benefits to those in other forms of encapsulation. The cost is that we must now write access methods, which in this situation are also referred to as delegation methods or forwarding methods since they delegate or forward operations to other objects.

Ex 8.3 step 1 Using delegation

The revised version of MuseumCountU is:
unit MuseumCountU;

// using delegation

interface

uses CounterU;

type
   TMuseumCount = class(TObject)
   private
     VEntered, VInside, VLeft: TCounter;
     // property mapping methods (use delegation)
     function GetEntered: integer;
     function GetInside: integer;
     function GetLeft: integer;
   public
     // read-only, method mapped properties using delegation
     property Entered: integer read GetEntered;
     property Inside: integer read GetInside;
     property Left: integer read GetLeft;
     constructor Create;
     procedure Arrivals (aNumber: integer) ;
     procedure ClearAll;
     procedure Departures (aNumber: integer) ;
   end;

implementation

{ TMuseumCount }

procedure TMuseumCount.Arrivals(aNumber: integer) ;
begin
   VEntered.Add (aNumber) ;
   VInside.Add (aNumber) ;
end;

procedure TMuseumCount.Departures(aNumber: integer) ;
begin
   VInside.Subtract (aNumber) ;
   VLeft.Add (aNumber) ;
end;

function TMuseumCount.GetEntered: integer;
begin
   Result := VEntered.Total;
end;

function TMuseumCount.GetInside: integer;
begin
   Result := VInside.Total;
end;

function TMuseumCount.GetLeft: integer;
begin
   Result := VLeft.Total;
end;

procedure TMuseumCount.ClearAll;
begin
   VEntered.Clear;
   VInside.Clear;
   VLeft.Clear;
end;

constructor TMuseumCount.Create;
begin
   // propagate construction
   inherited Create;
   VEntered := TCounter.Create;
   VInside := TCounter.Create;
   VLeft := TCounter.Create;
end;

end.
We have made the data fields private (line 8) with the result that we have to create six access methods. Three of these are mapped to read-only properties (VEntered, VInside and VLeft). The other three are mutator methods, though not Set methods (Arrivals, Departures and ClearAll).

These access methods all interact with the TCounter objects: TMuseumCount delegates all the data storage and manipulation to its subordinate objects, freeing the user interface from any concern over the details of the application logic.

From a different perspective, we can also say that the TMuseumClass is a composed class with three constituent TCounter objects: TMuseumCount is composed of (HasA) VEntered, VInside and VLeft objects.

Ex 8.3 step 2 Using the delegated methods

To use the new version of TMuseumCount we change the two OnClick event handlers in the user interface class as follows:
procedure TfrmAttendance.btnEnterClick(Sender: TObject) ;
begin
   MuseumCount.Arrivals (sedEnter.Value) ;
   lblIn.Caption := IntToStr(MuseumCount.Entered) ;
   lblVisitors.Caption := IntToStr(MuseumCount.Inside) ;
   sedEnter.Value := 0;
end;

procedure TfrmAttendance.btnLeaveClick(Sender: TObject) ;
begin
   with MuseumCount do
   begin
     Departures (sedLeave.Value) ;
     lblOut.Caption := IntToStr(Left) ; // ** dangerous??
     lblVisitors.Caption := IntToStr(Inside) ;
   end;
   sedLeave.Value := 0;
end;
Zarko Gajic
Guide since 1998

Zarko Gajic
Delphi Programming Guide

Explore Delphi Programming

More from About.com

Delphi Programming

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Coding Delphi Applications
  5. OOP in Delphi
  6. Free Online OOP Course
  7. Indirection - Delphi OOP Part 8 - Chapter 18

©2008 About.com, a part of The New York Times Company.

All rights reserved.