问题描述
我正在学习COM和Interfaces,并有以下实验代码:
type
IA = interface )
['{C9C5C992-3F67-48C5-B215-7DCE6A61F0E8}']
end;
IB = interface(IA)
['{F1799437-AD12-471B-8716-F1D93D1692FC}']
end;
IC = interface(IB)
['{01780E8C-C47D-468E-8E42-4BFF3F495D51}']
end;
TBO = class(TInterfacedObject,IB)
end;
procedure TForm1.FormCreate(Sender:TObject);
var
x:TBO;
a:IInterface;
begin
x:= TBO.Create;
IInterface(x)._ AddRef;
如果Assigned(TBO.GetInterfaceEntry(IA))then memo1.lines.add('GetInterfaceEntry IA:OK'); // 为什么不?
if Assigned(TBO.GetInterfaceEntry(IB))then memo1.lines.add('GetInterfaceEntry IB:OK');
if Assigned(TBO.GetInterfaceEntry(IC))then memo1.lines.add('GetInterfaceEntry IC:OK');
if x.QueryInterface(IA,a)= S_OK then memo1.lines.add('QueryInterface TA:OK'); // 为什么不?
if x.QueryInterface(IB,a)= S_OK then memo1.lines.add('QueryInterface TB:OK');
if x.QueryInterface(IC,a)= S_OK then memo1.lines.add('QueryInterface TC:OK');
如果支持(TBO,IA),则memo1.lines.add('支持TA:OK'); // 为什么不?
if支持(TBO,IB)then memo1.lines.add('支持TB:OK');
if支持(TBO,IC)then memo1.lines.add('Supports TC:OK');
if支持(x,IA,a)then memo1.lines.add('支持(2)TA:OK'); // 为什么不?
if支持(x,IB,a)then memo1.lines.add('支持(2)TB:OK');
if支持(x,IC,a)then memo1.lines.add('支持(2)TC:OK');
end;
输出:
code> GetInterfaceEntry IB:OK
QueryInterface TB:OK
支持TB:OK
支持(2)TB:OK
但我需要:
GetInterfaceEntry IA:OK
GetInterfaceEntry IB:OK
QueryInterface TA:OK
QueryInterface TB:OK
支持TA:OK
支持TB:OK
支持(2)TA:OK
支持(2)TB:OK
我理解 IB
是由于接口继承的
IA
的超集。在我的理解中,由于 TBO
实现 IB
,它自动实现 IA
。但为什么 Supports()
, QueryInterface()
, GetInterfaceEntry()
return false?
如何查询 TBO
implements code>直接OR间接,即通过实现
IA
的超集?我需要两个静态类函数,如 GetInterfaceEntry
和一个动态对象引用变量,如 QueryInterface
。
这是Delphi的一个已知怪癖。即使 IB
继承自 IA
, TBO
IA
和 IB
检索两个接口。
TBO = class(TInterfacedObject,IA,IB)
/ pre>
我忘了技术原因。与编译器为
TBO
生成接口表的限制有关的一些事情。它不会自动包含继承的接口。I am learning about COM and Interfaces and have following experimental code:
type IA = interface(IInterface) ['{C9C5C992-3F67-48C5-B215-7DCE6A61F0E8}'] end; IB = interface(IA) ['{F1799437-AD12-471B-8716-F1D93D1692FC}'] end; IC = interface(IB) ['{01780E8C-C47D-468E-8E42-4BFF3F495D51}'] end; TBO = class(TInterfacedObject, IB) end; procedure TForm1.FormCreate(Sender: TObject); var x: TBO; a: IInterface; begin x := TBO.Create; IInterface(x)._AddRef; if Assigned(TBO.GetInterfaceEntry(IA)) then memo1.lines.add('GetInterfaceEntry IA: OK'); // Why not? if Assigned(TBO.GetInterfaceEntry(IB)) then memo1.lines.add('GetInterfaceEntry IB: OK'); if Assigned(TBO.GetInterfaceEntry(IC)) then memo1.lines.add('GetInterfaceEntry IC: OK'); if x.QueryInterface(IA, a)=S_OK then memo1.lines.add('QueryInterface TA: OK'); // Why not? if x.QueryInterface(IB, a)=S_OK then memo1.lines.add('QueryInterface TB: OK'); if x.QueryInterface(IC, a)=S_OK then memo1.lines.add('QueryInterface TC: OK'); if Supports(TBO, IA) then memo1.lines.add('Supports TA: OK'); // Why not? if Supports(TBO, IB) then memo1.lines.add('Supports TB: OK'); if Supports(TBO, IC) then memo1.lines.add('Supports TC: OK'); if Supports(x, IA, a) then memo1.lines.add('Supports(2) TA: OK'); // Why not? if Supports(x, IB, a) then memo1.lines.add('Supports(2) TB: OK'); if Supports(x, IC, a) then memo1.lines.add('Supports(2) TC: OK'); end;
Output:
GetInterfaceEntry IB: OK QueryInterface TB: OK Supports TB: OK Supports(2) TB: OK
But I need:
GetInterfaceEntry IA: OK GetInterfaceEntry IB: OK QueryInterface TA: OK QueryInterface TB: OK Supports TA: OK Supports TB: OK Supports(2) TA: OK Supports(2) TB: OK
I understand that
IB
is a superset ofIA
due to the Interface inheritance. In my understanding, sinceTBO
implementsIB
, it automatically implementsIA
. But why doesSupports()
,QueryInterface()
,GetInterfaceEntry()
return false?How do I query if
TBO
implementsIA
directly OR indirectly, i.e. by implementing a superset ofIA
? I need both, a static class function likeGetInterfaceEntry
and a dynamic object reference variant likeQueryInterface
.解决方案This is a known quirk of Delphi. Even though
IB
inherits fromIA
,TBO
must explicitly specify bothIA
andIB
in order forSupports()
to retrieve both interfaces.TBO = class(TInterfacedObject, IA, IB)
I forget the technical reason for this. Something to do with a limitation in how the compiler generates the interface table for
TBO
. It does not automatically include inherited interfaces.这篇关于如何检查类是否实现了一个接口,遵守超集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!