1. Computing

The Many Faces of Delphi Routines: Functions and Procedures

An Overview: Routine, Method, Method Pointer, Event Delegate, Anonymous method

By

With the inclusion of anonymous methods in Delphi 2009, Delphi language has a new weapon in its "what a routine can do and be used for, and how" arsenal.

Here's an overview of how and when and for what you can use various "types" of Delphi routines: functions and procedures, function and procedure pointers, methods and method pointers, anonymous methods...

Note: this article will not discuss scope of a routine / method. The location of a routine declaration determines its scope. It can be private to the unit, private to the "outer routine", unit level, public, etc.

This article will also not discuss routine parameters and how values are passed to and from the routines.

Standalone Routines

More or less all of the RTL routines are so called "standalone" routines. They are declared on a unit level, to call such a routine you need to know where it is declared - unit name, and the list of parameters it accepts.

An example is the ShowMessage procedure declared in the dialogs.pas unit, here's the declaration:

 procedure ShowMessage(const Msg: string) ;
 
To call such a procedure, you simply need to include the unit name where this procedure is declared in the uses clause of the calling unit. Most of the common units are already listed in the uses clause of a form unit - thus you do not need to manually add "dialogs" to the uses clause to use the ShowMessage.

Nested Routines

Functions and procedures sometimes contain other functions and procedures within the local-declarations section of their blocks:
 function DoSomething(S: string) ;
 var
   X, Y: Integer;
 
   procedure NestedProc(S: string) ;
   begin
     ...
   end; //NestedProc
 begin
    ...
   NestedProc(S) ;
    ...
 end; //DoSomething
 
The above two "types" of routine declaration are *not* related to some class or an object.

Methods

Routines that are associated with a class are called methods. Most methods operate on class instances - objects. Some methods, called class methods, operate on classes.

The Add function is a method of a TStringList class, for example. The TStringList's Add method (a function) is declared as:

 function Add(const S: string): Integer;
 

Procedural Types and Procedure Pointers

Delphi lets you treat routines (functions and procerdures) as values that can be assigned to variables.

Consider the nest code segment:

 type
   TDisplayerProc = procedure(const s : string) ;
   TIntegerDisplayerFunc = function(const v : integer; dp : TDisplayerProc) : boolean;
 
 ...
 
 procedure Displayer (const s : string) ;
 begin
   ShowMessage(s) ;
 end;
 
 function DisplayDoubleInteger(const v : integer; dp : TDisplayerProc) : boolean;
 var
   r : integer;
 begin
   r := v + v;
   dp(IntToStr(r)) ;
 
   result := r > 0;
 end;
 
 .......
 
 var
   dp : TDisplayerProc;
   idf : TIntegerDisplayerFunc;
 begin
   dp := Displayer;
   dp('hello') ; //will "ShowMessage('hello')"
   dp('delphi') ; //will "ShowMessage('delphi')"
 
   idf := DisplayDoubleInteger;
 
   //what will this do?
   if idf(2009, dp) then
     ShowMessage('true')
   else
     ShowMessage('false') ;
 end;
 
In the above code section, the TDisplayerProc and TIntegerDisplayerFunc are procedural types.

Variables dp and idp are procedure pointers. Note that the DisplayDoubleInteger function takes a procedural type as its second parameter (TDisplayerProc).

Method Pointers

Similar to procedural pointers, method pointers reference a method of an instance object.

Here's one method pointer example:

 TDisplayMethod = procedure(const s : string) of object;
 
 TDeveloper = class
 private
   fName: string;
   fOnNameChanged: TDisplayMethod;
   procedure SetName(const Value: string) ;
 published
   property Name : string read fName write SetName;
   property OnNameChanged : TDisplayMethod read fOnNameChanged write fOnNameChanged;
 end;
 
 TForm1 = class(TForm)
   procedure FormCreate(Sender: TObject) ;
 private
   procedure ValueDisplayer(const s : string) ;
 end;
 
 ...
 
 procedure TForm1.FormCreate(Sender: TObject) ;
 var
   d : TDeveloper;
 begin
   d := TDeveloper.Create;
   try
     d.OnNameChanged := ValueDisplayer;
     d.Name := 'Marko';
     d.Name := 'zarko';
   finally
     d.Free;
   end;
 end;
 
 procedure TForm1.ValueDisplayer(const s: string) ;
 begin
   ShowMessage(s) ;
 end;
 
 { TDeveloper }
 
 procedure TDeveloper.SetName(const Value: string) ;
 begin
   if fName <> Value then
     if Assigned(fOnNameChanged) then fOnNameChanged('old name: ' + fName) ;
 
   fName := Value;
 end;
 

Anonymous Methods

With Delphi 2006, the Delphi language also has anonymous methods (known also as closuers).

An anonymous method is a procedure or function that does not have a name associated with it.

An example of anonymous methods is: sorting a generic TList object. For more on anoymous methods in Delphi, read: Understanding Anonymous Methods in Delphi.

©2014 About.com. All rights reserved.