使用Supports()函数与通用接口类型 [英] Use of Supports() function with generic interface type

查看:201
本文介绍了使用Supports()函数与通用接口类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在Delphi 2009中尝试我的第一次使用泛型,并且对如何使用通用类型作为用于查看对象是否实现给定接口的Supports函数的输入感到困惑。我创建了一个小例子来说明问题。



给定以下类型和实用程序函数:

  IMyInterface = interface 
['{60F37191-5B95-45BC-8C14-76633826889E}']
end;

TMyObject = class(TInterfacedObject,IMyInterface)
end;

类函数TFunctions.GetInterface< T>(myObject:TObject):T;
var
specificInterface:T;
begin
//这将编译,但失去通用功能
//支持(myObject,IMyInterface,specificInterface);

//这导致编译错误
支持(myObject,T,specificInterface);

result:= specificInterface;
结束

和以下代码片段:

 类程序TFunctions.Test; 
var
myObject:TMyObject;
myInterface:IMyInterface;
begin
myObject:= TMyObject.Create;

myInterface:= GetInterface< IMyInterface>(myObject);
结束

我希望没有问题,但是我收到以下编译时错误:

$ b $ E $($)$ {$ $ $ $ $ $ $ $ $ $ $ $)))))))))))))))))))))))))))))))))))))))))))))) :E2014声明预期,但表达式'T'发现


我不知道编译器期望我做什么T用作函数的实际参数。



我已经搜索了很多,并没有能够破解这一个。怀疑如果我可以理解在编译期间如何将接口名称转换为IID:TGUID类型,那么在使用具体的接口名称时,我可以做一些进展,但这也回避了我。



非常感谢任何帮助。

解决方案

不能保证T与之相关联的GUID,而且语言上没有办法在类型参数上写一个约束来做出这个保证。



编译器在接口名称中转换为GUID,查找符号表中的名称,获取编译器的表示接口的数据结构,并检查GUID的相应字段。但泛型不像C ++模板;它们需要被编译和类型检查并被认为适用于任何有效的类型参数,这意味着在其声明中约束类型参数。



您可以获得GUID使用RTTI(首先检查T确实代表一个界面),像 GetTypeData(TypeInfo(T))^。Guid 并将GUID传递给支持


I just tried my first use of generics in Delphi 2009 and am perplexed on how to use a generic type as the input to the Supports function used to see if an object implements a given interface. I've created a small sample illustrating the problem.

Given the following types and utility function:

IMyInterface = interface
['{60F37191-5B95-45BC-8C14-76633826889E}']
end;

TMyObject = class(TInterfacedObject, IMyInterface)
end;

class function TFunctions.GetInterface<T>(myObject: TObject): T;
var
  specificInterface: T;
begin
  // This would compile, but looses the generic capability
  //Supports(myObject, IMyInterface, specificInterface);

  // This results in compile errors
  Supports(myObject, T, specificInterface);

  result := specificInterface;
end;

and the following code snippet:

class procedure TFunctions.Test;
var
  myObject: TMyObject;
  myInterface: IMyInterface;
begin
  myObject := TMyObject.Create;

  myInterface := GetInterface<IMyInterface>(myObject);
end;

I would expect no problems but I get the following compile time errors:

[DCC Error] GenericExample.pas(37): E2029 '(' expected but ',' found [DCC Error] GenericExample.pas(37): E2014 Statement expected, but expression of type 'T' found

I'm not sure what the compiler is expecting me to do with the T when used as the actual argument to the function.

I've searched around quite a bit and haven't been able to crack this one. A part of me suspects that if I could understand how an interface name gets converted to the IID: TGUID type during compilation, when using a concrete interface name, I could make some headway, but that has evaded me also.

Any help is much appreciated.

解决方案

There is no guarantee that T has a GUID associated with it, and there is no means in the language to write a constraint on the type parameter to make that guarantee.

The interface name is converted into a GUID by the compiler looking up the name in the symbol table, getting the compiler's data structure representing the interface, and checking the corresponding field for the GUID. But generics are not like C++ templates; they need to be compiled and type-checked and known to work for any valid type parameter, and that means constraining the type parameter in its declaration.

You can get the GUID using RTTI (first checking that T does indeed represent an interface) with something like GetTypeData(TypeInfo(T))^.Guid and pass the GUID to Supports that way.

这篇关于使用Supports()函数与通用接口类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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