10.7 Usage

Once a helper class is defined, its methods can be used whenever the helper class is in scope. This means that if it is defined in a separate unit, then this unit should be in the uses clause wherever the methods of the helper class are used.

Consider the following unit:

{$mode objfpc}
{$h+}
unit oha;

interface

Type
  TObjectHelper = class helper for TObject
    function AsString(const aFormat: String): String;
  end;

implementation

uses sysutils;

function TObjectHelper.AsString(const aFormat: String): String;

begin
  Result := Format(aFormat, [ToString]);
end;

end.

Then the following will compile:

Program Example113;

uses oha;

{ Program to demonstrate the class helper scope. }

Var
  o : TObject;

begin
  O:=TObject.Create;
  Writeln(O.AsString('O as a string : %s'));
end.

But, if a second unit (ohb) is created:

{$mode objfpc}
{$h+}
unit ohb;

interface

Type
  TAObjectHelper = class helper for TObject
    function MemoryLocation: String;
  end;

implementation

uses sysutils;

function TAObjectHelper.MemoryLocation: String;

begin
  Result := format('%p',[pointer(Self)]);
end;

end.

And is added after the first unit in the uses clause:

Program Example113;

uses oha,ohb;

{ Program to demonstrate the class helper scope. }

Var
  o : TObject;

begin
  O:=TObject.Create;
  Writeln(O.AsString('O as a string : %s'));
  Writeln(O.MemoryLocation);
end.

Then the compiler will complain that it does not know the method “AsString”. This is because the compiler stops looking for class helpers as soon as the first class helper is encountered. Since the ohb unit comes last in the uses clause, the compiler will only use TAObjectHelper as the class helper.

The solution is to re-implement unit ohb:

{$mode objfpc}
{$h+}
unit ohc;

interface

uses oha;

Type
  TAObjectHelper = class helper(TObjectHelper) for TObject
    function MemoryLocation: String;
  end;

implementation

uses sysutils;

function TAObjectHelper.MemoryLocation: String;

begin
  Result := format('%p',[pointer(Self)]);
end;

end.

And after replacing unit ohb with ohc, the example program will compile and function as expected.

Note that it is not enough to include a unit with a class helper once in a project; The unit must be included whenever the class helper is needed.