Class and Record Helpers (Delphi)
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.
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
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;