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.