Delphi接口通用功能 - 有没有解决方法?

时间:2013-05-14 00:11:22

标签: delphi generics interface

我有以下代码

IProxy<T> = interface
  ['{1E3A98C5-78BA-4D65-A4BA-B6992B8B4783}']
  function Setup : ISetup<T>;
  function Proxy : T;
  function CastAs<I : IInterface> : IInterface;
end;

有没有办法解决编译时收到的编译器错误?

“[DCC错误] Delphi.Mocks.pas(123):E2535接口方法必须没有参数化方法”

基本上我想让这个接口传递并能够通过传入类型转换为并返回该类型来抛弃它。我可以用一个类实现这个,但是更喜欢绕过一个接口。

其他信息:

说我有以下课程

TInterfaceProxy<T> = class(TBaseProxy<T>)
private type
  TProxyVirtualInterface = class(TVirtualInterface)
  private
    FProxy : TInterfaceProxy<T>;
  protected
  public
    function QueryInterface(const IID: TGUID; out Obj): HRESULT; override; stdcall;
    constructor Create(AProxy : TInterfaceProxy<T>; AInterface: Pointer; InvokeEvent: TVirtualInterfaceInvokeEvent);
  end;
private
  FVirtualInterfaces : TDictionary<TGUID, TProxyVirtualInterface>;
protected
  function InternalQueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
  function QueryInterface(const IID: TGUID; out Obj): HRESULT; override;
  function Proxy : T;override;
  function CastAs<I: IInterface> : I;
public
  constructor Create;override;
  destructor Destroy;override;
end;

CastAs在这里运行良好,因为新请求的强制转换可以创建一个新的虚拟接口。现在,如果我想通过它的罚款。但是,如果我要求它作为接口,即TInterfaceProxy<T> = class(TBaseProxy<T>, IProxy<T>),它就无法理解。不同意,但明白。

因此,我如何解决这个限制,以便我可以调用CastAs函数,传入一个类型(任何接口类型开始),并能够从中创建虚拟接口?

2 个答案:

答案 0 :(得分:14)

接口不支持通用参数化方法,正如编译器所说。

没有解决方法,因为这是一个基本限制。类中的参数化方法是通过向每个实例添加一个方法来实现的。这适用于类,因为它们是具体的,但不适用于接口。这是因为接口是一个函数表,并且该表的大小不能根据代码中其他地方碰巧出现的泛型方法实例而变化。出于类似的原因,通用方法不能是虚拟的或动态的。

你问题中的代码也有点误导。你写道:

function CastAs<I : IInterface> : IInterface;

但我确定你的意思是:

function CastAs<I : IInterface> : I;

无论如何,这是不可能的。一种选择是使用类来代替。我同意这是一个约束。

如果你想在界面中这样做,你可以做的最好的是:

function CastAs(const IID: TGUID): IInterface;

但是你必须这样称呼它:

MyIntf := ProxyIntf.CastAs(IMyIntf) as IMyIntf;
感觉有点犯规。

选择你的毒药!

答案 1 :(得分:5)

如错误消息所述,接口中的方法不能具有通用参数。编译器根本不支持它,并且记录如下:

http://docwiki.embarcadero.com/RADStudio/XE4/en/Overview_of_Generics

  

界面中的参数化方法

     

参数化方法(使用类型参数声明的方法)不能在接口中声明。

换句话说,您的CastAs方法是非法的,因为它是在接口类型中声明的。另一方面,您首先不需要这样的方法。您可以使用SysUtils.Supports()代替将一个接口转换为另一个接口。