I found a (at least for me) unexpected behavior when using interface inheritance in Delphi.
I have this simple class and interface hierarchy:
+---------------+
| << IMyBase >> |
+---------------+
^
|
+---------------+
| << IMyIntf >> |
+---------------+
^
|
+---------+
| TMyObj |
+---------+
I wanted to declare a variable of type IMyBase
. Create a TMyObj
and assign it to my variable. IHMO this is normal OOP practice. But it turned out that it does not compile.
I Have also tried to declare a variable of type IMyIntf
and check if it supports IMyBase
, IMHO it should support it, but it doesn't.
Here is a simple test code:
program interface_inheritance;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
IMyBase = interface
['{CC7C61B8-3FBA-481F-AF0D-A93C603B5202}']
procedure Hello;
end;
IMyIntf = interface(IMyBase)
['{01CE01D9-A753-431C-A30E-64BAEC6C4E26}']
//
end;
TMyObj = class(TInterfacedObject, IMyIntf)
procedure Hello;
end;
{ TMyObj }
procedure TMyObj.Hello;
begin
Writeln('Hello World');
end;
var
b: IMyBase;
i: IMyIntf;
begin
(* // Compile Error E2010
b := TMyObj.Create;
b.Hello;*)
// Does not work as Expected
// Does not call Hello()
i := TMyObj.Create;
if Supports(i, IMyBase, b) then begin
// Why does i not support IMyBase ??
b.Hello;
end;
// Works but unsafe!
// Hard cast, without check.
i := TMyObj.Create;
b := IMyBase(i);
b.Hello;
// Works, of course!
i := TMyObj.Create;
i.Hello;
Readln;
end.
As you can see i have a valid class/interface structure. but some parts do not compile. and some do not execute as expected.
- Why does
b := TMyObj.Create;
give an incompatible type error? - Why does
Supports(i, IMyBase, b)
returnsfalse
? - Is there another (better) way to solve such a problem? without a hard cast without check? (
if i is IMyBase
does not work, because interfaces do not supportis
operator.)
Is this valid Pascal/Delphi behavior or a bug? IMHO Supports()
should return true
. and TMyObj
should be a valid IMyBase
(and therefor be assignable).