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.