11.3 Formal declaration

Object Pascal has the concept of Forward declarations. Objective-C takes this concept a bit further: it allows to declare a class which is defined in another unit. This has been dubbed “Formal declaration” in Objective-Pascal. Looking at the syntax diagram, the following is a valid declaration:

MyExternalClass = objcclass external;

This is a formal declaration. It tells the compiler that MyExternalClass is an Objective-C class type, but that there is no declaration of the class members. The type can be used in the remainder of the unit, but its use is restricted to storage allocation (in a field or method parameter definition) and assignment (much like a pointer).

As soon as the class definition is encountered, the compiler can enforce type compatibility.

The following unit uses a formal declaration:

unit ContainerClass;  
 
{$mode objfpc}  
{$modeswitch objectivec1}  
 
interface  
 
type  
  MyItemClass = objcclass external;  
 
  MyContainerClass = objcclass  
    private  
     item: MyItemClass;  
    public  
     function getItem: MyItemClass; message ’getItem’;  
  end;  
 
implementation  
 
function MyContainerClass.getItem: MyItemClass;  
begin  
  result:=item; // Assignment is OK.  
end;  
 
end.

A second unit can contain the actual class declaration:

unit ItemClass;  
 
{$mode objfpc}  
{$modeswitch objectivec1}  
 
interface  
 
type  
  MyItemClass = objcclass(NSObject)  
  private  
    content : longint;  
  public  
    function initWithContent(c: longint): MyItemClass;  
       message ’initWithContent:’;  
     function getContent: longint;  
       message ’getContent’;  
  end;  
 
implementation  
 
function MyItemClass.initWithContent(c: longint):  
   MyItemClass;  
begin  
  content:=c;  
  result:=self;  
end;  
 
function MyItemClass.getContent: longint;  
begin  
  result:=content;  
end;  
 
end.

If both units are used in a program, the compiler knows what the class is and can verify the correctness of some assignments:

Program test;  
 
{$mode objfpc}  
{$modeswitch objectivec1}  
 
uses  
  ItemClass, ContainerClass;  
 
var  
  c: MyContainerClass;  
  l: longint;  
begin  
  c:=MyContainerClass.alloc.init;  
  l:=c.getItem.getContent;  
end.