在使用Delphi中的接口继承时,我发现了一个(至少对我来说)意外的行为。
我有这个简单的类和接口层次结构:
+---------------+
| << IMyBase >> |
+---------------+
^
|
+---------------+
| << IMyIntf >> |
+---------------+
^
|
+---------+
| TMyObj |
+---------+
我想声明一个类型为 IMyBase
的变量。创建一个 TMyObj
并将其赋值给我的变量。在我看来,这是正常的面向对象编程实践。但是结果表明它无法编译。
我还尝试声明一个类型为 IMyIntf
的变量,并检查它是否支持 IMyBase
,在我看来它应该支持,但它并不支持。
这里是一个简单的测试代码:
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.
你可以看到我有一个有效的类/接口结构,但是有些部分无法编译,而有些部分则无法按预期执行。
- 为什么
b := TMyObj.Create;
会出现不兼容类型错误? - 为什么
Supports(i, IMyBase, b)
返回false
? - 是否有另一种(更好的)方法来解决这样的问题?不需要硬转换也不需要检查吗?(
if i is IMyBase
不起作用,因为接口不支持is
运算符。)
这是有效的Pascal/Delphi行为还是一个错误?在我看来,Supports()
应该返回 true
,并且 TMyObj
应该是有效的 IMyBase
(因此可分配)。