The general function of the Delphi interface - is there any work?

I have the following code

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

Is there a way around the compiler error that was received during compilation?

"[DCC Error] Delphi.Mocks.pas (123): E2535 Interface methods must not have parameterized methods"

Basically, I would like this interface to be passed, and it will be able to discard it by passing the type to be sent and return that type. I can achieve this with a class, but would prefer going through the interface.

Additional Information:

Say I have the following class

 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 works well here, as the recently requested cast can be created with a new virtual interface. Now, if I want to go through this class around his fine. However, if I require it as an interface, that is, TInterfaceProxy<T> = class(TBaseProxy<T>, IProxy<T>) , this will not work. Do not disagree with this, but understand.

Therefore, how can I get around this restriction so that I can call the CastAs function, pass in a type (any type of interface to start with) and be able to create a virtual interface from it?

+6
source share
2 answers

Interfaces do not support generic parameterized methods, as the compiler says.

There is no workaround as this is a fundamental limitation. Parameterized methods in classes are implemented by adding one method per class instance. This works for classes as they are concrete, but not suitable for interfaces. This is because interfaces are a table of functions, and the size of this table cannot vary depending on which instances of generic methods are present elsewhere in the code. For similar reasons, general methods cannot be virtual or dynamic.

The code in your question is also a bit wrong. You wrote:

 function CastAs<I : IInterface> : IInterface; 

but I'm sure you mean:

 function CastAs<I : IInterface> : I; 

In any case, this is not possible. One option is to use a class instead. I agree that this is a binding.

If you want to do this in an interface, the best thing you can do:

 function CastAs(const IID: TGUID): IInterface; 

But you have to call it like this:

 MyIntf := ProxyIntf.CastAs(IMyIntf) as IMyIntf; 

which feels somewhat dirty.

Choose your poison!

+12
source

As indicated in the error message, the method in the interface cannot have common parameters. The compiler simply does not support it, and this is documented as such:

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

Parameterized Method in Interface

A parameterized method (a method declared with type parameters) cannot be declared in an interface.

In other words, your CastAs method is illegal because it is declared in an interface type. On the other hand, you do not need such a method in the first place. You can use SysUtils.Supports() instead of imposing one interface on another.

+5
source

Source: https://habr.com/ru/post/944937/


All Articles