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