7.4 Interface inheritance

It is possible to let one interface be a descendent from another interface:

IParentInterface = interface  
  [’{0F78D56E-85A6-4024-98D7-720D7C7B9573}’]  
  procedure Foo;  
end;  
 
IChildInterface = interface(IParentInterface)  
  [’{1AB2EB85-6843-462E-8CE4-32ECC065011E}’]  
  procedure Bar;  
end;

IChildInterface will have two methods: foo and bar. Any class implementing this interface will therefore need to implement both interfaces:

TImplementor = class(TInterfacedObject, IChildInterface)  
public  
  procedure Foo;  
  procedure Bar;  
end;  
 
procedure TImplementor.Foo;  
begin  
 
end;  
 
procedure TImplementor.Bar;  
begin  
 
end;

Note that when a class declares a child interface, it can be assigned to a variable with the child interface. Given the above declarations, the following will compile:

var  
  Child: IChildInterface;  
 
begin  
  Child := TImplementor.Create;

But this does not imply that it automatically also is assignment compatible with a variable with the type of parent interface. The following will not compile:

var  
  Parent: IParentInterface;  
 
begin  
  Parent := TImplementor.Create;

To make this compile, it is necessary to declare the class as:

TImplementor = class(TInterfacedObject,  
                     IParentInterface,  
                     IChildInterface)  
public  
  procedure Foo;  
  procedure Bar;  
end;

The reason for this is that although the class actually implements the methods of IParentInterface, the compiler checks only actually declared interfaces when checking assignment compatibility: all declared interfaces are put in a table and only the contents of this table is checked.

The same check is performed at runtime: the compiler generates a table of all interfaces a class declares, and this table is checked at runtime. That means that although the following will compile if only IChildInterface is declared:

 ParentImplementorInstance := (TImplementor.Create as IParentInterface);

it will still fail with a run-time error:

home:~> ./ti  
An unhandled exception occurred at $0000000000411A27:  
EInvalidCast: Invalid type cast  
$0000000000411A27