2013-05-14 15 views
6

Ho il seguente codiceFunzione generica dell'interfaccia Delphi - C'è un problema?

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

C'è un modo per aggirare l'errore del compilatore che viene ricevuto durante la compilazione?

"[DCC errore] Delphi.Mocks.pas (123): i metodi E2535 di interfaccia non devono avere metodi parametrizzati"

Fondamentalmente vorrei avere questa interfaccia essere passati in giro ed essere in grado di lanciare fuori di esso, passando il tipo a cast e restituendo quel tipo. Posso ottenere questo risultato con una classe, tuttavia preferirei passare attorno a un'interfaccia.

Informazione supplementare:

Dire che ho la seguente classe

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 funziona bene qui come il cast di nuova richiesta può essere creata una nuova interfaccia virtuale. Ora, se voglio passare questa lezione in modo corretto. Tuttavia se lo richiedo come interfaccia, ovvero TInterfaceProxy<T> = class(TBaseProxy<T>, IProxy<T>), non funziona, capiscilo. Non sono d'accordo, ma capisci.

Quindi, come faccio ad aggirare questa restrizione in modo da poter chiamare una funzione CastAs, passare un tipo (qualsiasi tipo di interfaccia per iniziare) ed essere in grado di creare un'interfaccia virtuale da esso?

risposta

12

Le interfacce non supportano metodi parametrici generici, come dice il compilatore.

Non c'è soluzione alternativa perché è un limite fondamentale. I metodi parametrizzati nelle classi sono implementati aggiungendo un metodo per istanziazione alla classe. Questo funziona per le classi poiché sono concreti, ma non è fattibile per le interfacce. Questo perché le interfacce sono una tabella di funzioni e la dimensione di quella tabella non può variare a seconda di quali istanze di metodo generico sono presenti altrove nel codice. Per ragioni simili, i metodi generici non possono essere virtuali o dinamici.

Il codice nella tua domanda è un po 'fuorviante anche.Hai scritto:

function CastAs<I : IInterface> : IInterface; 

ma sono sicuro che volevi dire:

function CastAs<I : IInterface> : I; 

In ogni caso, non è possibile. Un'opzione è usare invece una classe. Sono d'accordo che questo è un legame.

Se si vuole fare in un'interfaccia, il meglio che puoi fare è:

function CastAs(const IID: TGUID): IInterface; 

ma avresti dovuto chiamare in questo modo:

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

che si sente un po 'fallo .

Scegli il tuo veleno!

+0

Grazie. Credo che dovrò passare per il passaggio del TGUID e vivere con quello. Inoltre esporrà la classe esternamente, ma manterrà l'interfaccia "function CastAs (const IID: TGUID): IInterface;" interno. Vorrei poter "programmare nella tua lingua, non in esso" http://programmers.stackexchange.com/questions/2777/what-are-the-key-points-of-code-completo – Jason

+0

Inoltre sì, la tua corretta su ' function CastAs : I; 'un errore sul mio copiare il codice. – Jason

5

Come indica il messaggio di errore, un metodo in un'interfaccia non può avere parametri generici. Il compilatore semplicemente non lo supporta, e questo è documentato come tale:

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

metodo con parametri nell'interfaccia

Procedimento parametrizzato (metodo dichiarato con parametri di tipo) non può essere dichiarato un'interfaccia

In altre parole, il metodo CastAs è illegale perché è dichiarato in un tipo di interfaccia. D'altra parte, non è necessario un tale metodo in primo luogo. È possibile utilizzare SysUtils.Supports() invece di trasmettere un'interfaccia a un'altra.

+0

Capire, non direttamente il problema. Renditi conto di ciò che dice il compilatore e perché è un problema per Delphi. Non sono d'accordo con il design, tuttavia cerco un motivo per cui progettare il mio lavoro con i limiti di Delphi. Attualmente sto pensando che passare l'oggetto sia l'unica via purtroppo. Grazie per i commenti. – Jason