【问题标题】:When a class implements a descendant interface, why doesn't it automatically count as implementing the base interface?当一个类实现了后代接口时,为什么它不自动算作实现了基接口?
【发布时间】:2012-01-18 01:42:07
【问题描述】:

这不会编译的原因是什么?

type
  IInterfaceA = interface ['{44F93616-0161-4912-9D63-3E8AA140CA0D}']
    procedure DoA;
  end;

  IInterfaceB = interface(IInterfaceA) ['{80CB6D35-E12F-462A-AAA9-E7C0F6FE0982}']
    procedure DoB;
  end;

  TImplementsAB = class(TSingletonImplementation, IInterfaceB)
    procedure DoA;
    procedure DoB;
  end;

var
  ImplementsAB: TImplementsAB;
  InterfaceA: IInterfaceA;
  InterfaceB: IInterfaceB;
begin
  ImplementsAB := TImplementsAB.Create;
  InterfaceA := ImplementsAB; >> incompatible types
  ...
end

相比之下,这是我的工作方式:

InterfaceA := ImplementsAB as InterfaceB;

InterfaceA := InterfaceB;

我的意思是,如果 IInterfaceB 继承自 IInterfaceA 而 TImplementsAB 实现了 IInterfaceB,那么同时实现 IInterfaceA 并且类型兼容就不合逻辑了吗?

【问题讨论】:

    标签: delphi interface delphi-2010


    【解决方案1】:

    之所以如此,是因为早期的 OLE/COM 有一个错误,而 Borland 决定与之兼容。本文中提到了这一点:New Delphi language feature: Multiple inheritance for interfaces in Delphi for .NET。解决方案是像 Mikael 所写的那样,在类中显式列出所有祖先接口。

    链接文章中的一些引述:

    问题出在 COM 本身。为了加载一个模块,COM 将加载 DLL,GetProcAddress 在一个众所周知的入口点上,该入口点应该从 DLL 中导出,调用 DLL 函数来获得一个 IUnknown 接口,然后是 IClassFactory 的 QueryInterface。问题是,当 Microsoft 添加对 IClassFactory2 的支持时,他们在查询 IClassFactory 的现有代码之后添加了 IClassFactory2 的 QueryInterface。仅当 IClassFactory 查询失败时才会请求 IClassFactory2。

    因此,COM 永远不会在任何实现了 IClassFactory2 和 IClassFactory 的 COM 服务器上请求 IClassFactory2。

    这个 bug 在 COM 中存在很长时间了。微软表示,他们无法使用操作系统服务包修复 COM 加载程序,因为 Word 和 Excel(当时)都依赖于错误行为。不管它是否在最新版本的 COM 中得到修复,Borland 都必须提供一些方法来在可预见的未来在 Win32 Delphi 中保留这种行为。突然将所有祖先添加到以前不存在的实现类中很可能会破坏现有代码,这些代码无意中落入与 COM 加载器相同的模式。

    【讨论】:

    • @AllenBauer 我从我链接的文章中添加了一些引用。
    • 哇。谈论您从未抽出时间去追求的旧的未决指针。很久以前我有这个完全相同的问题,只是将额外的接口添加到列表中,以解决当时似乎不必要的任务。很高兴看到这不是 Borland 的错误,而是保持跨旧应用程序兼容性的合乎逻辑的决定。
    【解决方案2】:

    另一种方法是在类声明中包含这两个接口。

    TImplementsAB = class(TSingletonImplementation, IInterfaceA, IInterfaceB)
      procedure DoA;
      procedure DoB;
    end;
    

    我想这就是编译器实现TImplementsAB 实现IInterfaceAIInterfaceB 所需要的。

    【讨论】:

      猜你喜欢
      • 2015-01-15
      • 2018-10-24
      • 2016-04-28
      • 2012-04-30
      • 2013-09-30
      • 2016-11-30
      • 2011-04-24
      • 2014-09-16
      • 2019-09-16
      相关资源
      最近更新 更多