当一个类实现后代接口时,为什么它不会自动计算为实现基本接口? [英] When a class implements a descendant interface, why doesn't it automatically count as implementing the base interface?

查看:85
本文介绍了当一个类实现后代接口时,为什么它不会自动计算为实现基本接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个不能编译的原因是什么?

  type 
IInterfaceA = interface ['{44F93616-0161 -4912-9D63-3E8AA140CA0D}']
过程DoA;
结束

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

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

var
ImplementsAB:TImplementsAB;
InterfaceA:IInterfaceA;
InterfaceB:IInterfaceB;
begin
ImplementsAB:= TImplementsAB.Create;
InterfaceA:= ImplementsAB; >>不兼容的类型
...
end

相反,这是我做的它工作:

  InterfaceA:= ImplementsAB作为InterfaceB; 

  InterfaceA:= InterfaceB;我的意思是,如果IInterfaceB继承自IInterfaceA和TImplementsAB实现了IInterfaceB,那么也不符合逻辑实现IInterfaceA和类型兼容?

解决方案

这是因为早期的OLE / COM有一个错误,Borland决定与它兼容。这在本文中提到:新的Delphi语言功能:Delphi for .NET中接口的多重继承 。解决方案是列出Mikael写的类中明确的所有祖先接口。



链接文章中的一些引号:


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



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



这个bug存在于COM很长一段时间。微软表示,由于Word和Excel(当时)都依赖于错误的行为,因此无法使用OS服务包修复COM加载程序。无论是否在最新的COM版本中修复它,Borland必须提供一些方法来保护Win32 Delphi中的这种行为,以便将来可以预见。突然将所有祖先添加到以前不存在的实现类中,很可能会破坏与COM加载程序无关的现有代码。



What's the reason this won't compile?

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

In contrast this is how I make it work:

InterfaceA := ImplementsAB as InterfaceB;

or

InterfaceA := InterfaceB;

I mean, if IInterfaceB inherits from IInterfaceA and TImplementsAB implements IInterfaceB, it wouldn't be logical to also implement IInterfaceA and be type compatible?

解决方案

This so because early OLE/COM had a bug and Borland decided to be compatible with it. This is mentioned in this article: New Delphi language feature: Multiple inheritance for interfaces in Delphi for .NET. The solution is to list all ancestor interfaces explicitly in the class as Mikael wrote.

Some quotes from the linked article:

The problem was in COM itself. To load a module, COM would load the DLL, GetProcAddress on a well-known entry point that was supposed to be exported from the DLL, call the DLL function to obtain an IUnknown interface, and then QueryInterface for IClassFactory. The problem was, when Microsoft added support for IClassFactory2, they added the QueryInterface for IClassFactory2 after the existing code that queried for IClassFactory. IClassFactory2 would only be requested if the query for IClassFactory failed.

Thus, COM would never request IClassFactory2 on any COM server that implemented both IClassFactory2 and IClassFactory.

This bug existed in COM for a long time. Microsoft said that they couldn't fix the COM loader with an OS service pack because both Word and Excel (at the time) relied on the buggy behavior. Regardless of whether it's fixed in the latest releases of COM or not, Borland has to provide some way to preserve this behavior in Win32 Delphi for the forseeable future. Suddenly adding all ancestors into an implementing class that weren't there before is very likely to break existing code that unintentionally falls into the same pattern as the COM loader.

这篇关于当一个类实现后代接口时,为什么它不会自动计算为实现基本接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆