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.