【发布时间】:2011-03-19 05:12:34
【问题描述】:
在 Delphi 中,IUnknown 被声明为:
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
注意:输出参数无类型
在我的TInterfacedObject 后代中,我需要处理QueryInterface,所以我可以返回一个支持请求接口的对象:
function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID(IID, IFooBar) then
begin
Obj := (TFooBar.Create(Self) as IFooBar);
Result := S_OK;
end
else
Result := inherited QueryInterface(IID, {out}Obj);
end;
问题来了:
Obj := (TFooBar.Create(Self) as IFooBar);
德尔福抱怨:
运算符不适用于此操作数类型
显然我不知道如何或将什么分配给 untyped out 参数。我可以随机尝试一些东西,希望编译器不会抱怨:
Obj := TFooBar.Create(Self);
Obj := Pointer(TFooBar.Create(Self));
Obj := Pointer(TFooBar.Create(Self) as IFooBar);
忽略我编写的所有代码(如果需要):如何在 TInterfacedObject 的后代对象中实现 QueryInterface?
我一直试图解决的真正问题可以归结为我想要:
我想覆盖接口中的方法
同理:
TList = class(TObject)
...
function GetItem(Index: Integer): Pointer;
procedure SetItem(Index: Integer; Value: Pointer);
property Items[Index: Integer]: Pointer read GetItem write SetItem;
end;
可以在后代类中被覆盖:
TStudentList = class(TList)
...
function GetItem(Index: Integer): TStudent;
procedure SetItem(Index: Integer; Value: TStudent);
property Items[Index: Integer]: TStudent read GetItem write SetItem;
end;
我想对接口也一样:
IFoo = interface(IUnknown)
...
function GetItem(Index: Variant): Variant;
procedure SetItem(Index: Variant; Value: Variant);
property Items[Index: Variant]: Variant read GetItem write SetItem;
end;
IFooGuidString = interface(IFoo)
...
function GetItem(Index: TGUID): string ;
procedure SetItem(Index: TGUID; Value: string );
property Items[Index: TGUID]: string read GetItem write SetItem;
end;
问题是我必须如何开始加载我的实现对象:
TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
function IFoo.GetItem = FooGetItem;
procedure IFoo.SetItem = FooSetItem;
function FooGetItem(Index: Variant): Variant;
procedure FooSetItem(Index: Variant; Value: Variant);
function IFooGuidString.GetItem = FooGuidStringGetItem;
procedure IFooGuidString.SetItem = FooGuidStringSetItem;
function FooGuidStringGetItem(Index: TGUID): string ;
procedure FooGuidStringSetItem(Index: TGUID; Value: string );
end;
IFoo 中不仅有两个方法,还有 6 个。然后如果我想添加另一个支持的接口:
IFooInt64String = interface(IFoo)
...
function GetItem(Index: Int64): string ;
procedure SetItem(Index: Int64; Value: string );
property Items[Index: Int64]: string read GetItem write SetItem;
end;
TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
function IFoo.GetItem = FooGetItem;
procedure IFoo.SetItem = FooSetItem;
function FooGetItem(Index: Variant): Variant;
procedure FooSetItem(Index: Variant; Value: Variant);
function IFooGuidString.GetItem = FooGuidStringGetItem;
procedure IFooGuidString.SetItem = FooGuidStringSetItem;
function FooGuidStringGetItem(Index: TGUID): string ;
procedure FooGuidStringSetItem(Index: TGUID; Value: string );
function IFooInt64String.GetItem = FooInt64StringGetItem;
procedure IFooInt64String.SetItem = FooInt64StringSetItem;
function FooInt64StringGetItem(Index: Int64): string ;
procedure FooInt64StringSetItem(Index: Int64; Value: string );
end;
而且事情变得非常笨拙。
【问题讨论】:
-
我鼓励你也发布一个关于你的“真正问题”的问题。这听起来很有趣,而且我对如何做有一个模糊的想法(关于聚合 和容器)。您可能会发现自己编写的代码超出了您的需要。
-
@Rob Kennedy 如果您能想到一个有用的标题,这会引起人们的兴趣,我肯定会这样做。我发现如果没有一个好的hook,问题就没有答案。这个问题很好,因为这个问题,用措辞来说,听起来很简单——所以我在吸引那些认为他们能够给我一个轻松的教育的人。另一方面,你和 Uwe 似乎在为 Delphi 问题巡逻 :)
标签: delphi interface iunknown queryinterface