当一个类实现一个后代接口时,为什么它不会自动计为实现基接口?

pra*_*mer 18 delphi interface delphi-2010

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

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
Run Code Online (Sandbox Code Playgroud)

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

InterfaceA := ImplementsAB as InterfaceB;
Run Code Online (Sandbox Code Playgroud)

要么

InterfaceA := InterfaceB;
Run Code Online (Sandbox Code Playgroud)

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

ain*_*ain 28

这是因为早期的OLE/COM有一个错误,Borland决定与它兼容.本文提到了这一点:新的Delphi语言特性: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.

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

  • @AllenBauer我在我链接的文章中添加了一些引用. (2认同)

Mik*_*son 6

使其工作的另一种方法是在类声明中包含两个接口.

TImplementsAB = class(TSingletonImplementation, IInterfaceA, IInterfaceB)
  procedure DoA;
  procedure DoB;
end;
Run Code Online (Sandbox Code Playgroud)

我想这是编译器的认识到什么是需要TImplementsAB同时实现了IInterfaceAIInterfaceB.