Class and Record Helpers (Delphi)

From RAD Studio
Jump to: navigation, search

Go Up to Classes and Objects Index


This topic describes the syntax of class helper declarations.

About Class and Record Helpers

A class or a record helper is a type that - when associated with another class or a record - introduces additional method names and properties that may be used in the context of the associated type (or its descendants). Helpers are a way to extend a class without using inheritance, which is also useful for records that do not allow inheritance at all. A helper simply introduces a wider scope for the compiler to use when resolving identifiers. When you declare a class or a record helper, you state the helper name, and the name of the type you are going to extend with the helper. You can use the helper any place where you can legally use the extended class or record. The compiler's resolution scope then becomes the original type, plus the helper.

Class and record helpers provide a way to extend a type, but they should not be viewed as a design tool to be used when developing new code. For new code you should always rely on normal class inheritance and interface implementations.

Helper Syntax

The syntax for declaring a class helper is:

type
   identifierName = class|record helper [(ancestor list)] for TypeIdentifierName
     memberList
   end;

The ancestor list is optional. It can be specified only for class helper and it indicates an existing class helper extended by the current declaration.

A helper type may not declare instance data, but class fields are allowed.

The visibility scope rules and memberList syntax are identical to that of ordinary class and record types.

Note: Class and record helpers do not support operator overloading.

You can define and associate multiple helpers with a single type. However, only zero or one helper applies in any specific location in source code. The helper defined in the nearest scope will apply. Class or record helper scope is determined in the normal Delphi fashion (for example, right to left in the unit's uses clause).

Using Helpers

The following code demonstrates the declaration of a class helper (record helpers behave in the same manner):

 
 type
    TMyClass = class
       procedure MyProc;
       function  MyFunc: Integer;
    end;
 
    ...
 
    procedure TMyClass.MyProc;
    var X: Integer;
    begin
       X := MyFunc;
    end;
 
    function TMyClass.MyFunc: Integer;
    begin
        ...
    end;
 
 ...
 
 type
    TMyClassHelper = class helper for TMyClass
      procedure HelloWorld;
      function MyFunc: Integer;
    end;
 
    ...
 
    procedure TMyClassHelper.HelloWorld;
    begin
       Writeln(Self.ClassName); // Self refers to TMyClass type, not TMyClassHelper
    end;
 
    function TMyClassHelper.MyFunc: Integer;
    begin
      ...
    end;
 
 ...
 
 var
   X: TMyClass;
 begin
   X := TMyClass.Create;
   X.MyProc;    // Calls TMyClass.MyProc
   X.HelloWorld; // Calls TMyClassHelper.HelloWorld
   X.MyFunc;    // Calls TMyClassHelper.MyFunc
Tip: Keep in mind, the class helper function MyFunc is called, because the class helper takes precedence over the actual class type.

Class and record helpers do not work when intrinsic/enumerated types should be extended. For example:

type
    TMyEnum = (one, two, three);
    TMyEnumHelper = record helper for TMyEnum
      function GetNext: TMyEnum;
    end;

See Also