2013-05-14 4 views
6

Ich habe den folgenden CodeDelphi-Schnittstelle generische Funktion - Gibt es eine Arbeit?

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

Gibt es eine Möglichkeit, um den Compiler-Fehler zu arbeiten, die empfangen wird beim Kompilieren?

„[DCC Error] Delphi.Mocks.pas (123): Methoden E2535 Schnittstelle muss nicht parametriert Methoden haben“

Grundsätzlich ich diese Schnittstelle um der Lage weitergegeben haben möchte und dass es abzustreifen, indem Sie den Typ übergeben, an den der Typ übergeben und zurückgegeben werden soll. Ich kann das mit einer Klasse erreichen, würde aber lieber eine Schnittstelle weitergeben.

Zusätzliche Information:

sagen, dass ich die folgende Klasse eine neue virtuelle Schnittstelle erstellt werden können

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 gut funktioniert hier als die neu angeforderten Besetzung. Nun, wenn ich diese Klasse gut durchziehen will. Allerdings, wenn ich es als Schnittstelle, d. H. TInterfaceProxy<T> = class(TBaseProxy<T>, IProxy<T>) benötigen, funktioniert es nicht, dass zu verstehen. Stimme nicht damit überein, aber verstehe es.

Wie kann ich diese Einschränkung umgehen, so dass ich eine CastAs-Funktion aufrufen, einen Typ übergeben kann (einen beliebigen Schnittstellentyp) und in der Lage sein muss, daraus eine virtuelle Schnittstelle zu erstellen?

Antwort

12

Schnittstellen unterstützen keine generischen parametrisierten Methoden, wie der Compiler sagt.

Es gibt keine Problemumgehung, da dies eine grundlegende Einschränkung darstellt. Parametrisierte Methoden in Klassen werden implementiert, indem der Klasse eine Methode pro Instanz hinzugefügt wird. Das funktioniert für Klassen, da sie konkret sind, aber nicht für Schnittstellen geeignet sind. Das liegt daran, dass Schnittstellen eine Tabelle von Funktionen sind und die Größe dieser Tabelle nicht variieren kann, abhängig davon, welche generische Methode Instanzen an anderer Stelle im Code enthalten. Aus ähnlichen Gründen können generische Methoden nicht virtuell oder dynamisch sein.

Der Code in Ihrer Frage ist ein wenig irreführend auch.Sie schrieb:

function CastAs<I : IInterface> : IInterface; 

aber ich bin sicher, dass Sie gemeint:

function CastAs<I : IInterface> : I; 

Auf jeden Fall ist es nicht möglich ist. Eine Option besteht darin, stattdessen eine Klasse zu verwenden. Ich stimme zu, dass dies eine Bindung ist.

Wenn Sie es in einer Schnittstelle tun möchten, können das Beste, was Sie tun, ist:

function CastAs(const IID: TGUID): IInterface; 

Aber man müsste es so nennen:

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

die etwas Foul fühlt .

Wählen Sie Ihr Gift!

+0

Danke. Glauben Sie, ich werde für die TGUID gehen müssen und damit leben. Wird auch die Klasse extern offen legen, aber behalten Sie die Schnittstelle "Funktion CastAs (const IID: TGUID): IInterface;" intern. Wünschte, ich könnte "Programm in Ihre Sprache, nicht darin" http://programmers.stackexchange.com/questions/2777/what-are-the-keypoint-of-code-complete – Jason

+0

Auch ja Ihr richtig über die ' Funktion CastAs : I; 'ein Fehler beim Kopieren des Codes über. – Jason

5

Wie die Fehlermeldung besagt, kann eine Methode in einer Schnittstelle keine generischen Parameter haben. Der Compiler einfach nicht unterstützt, und dies wird als solche dokumentiert:

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

Parameterized Verfahren in der Schnittstelle

A parametrisierte Verfahren (Verfahren mit Typ-Parameter erklärt) kann nicht in deklariert werden eine Schnittstelle.

Mit anderen Worten, Ihre CastAs Methode ist illegal, da es in einem Schnittstellentyp deklariert ist. Auf der anderen Seite brauchen Sie eine solche Methode überhaupt nicht. Sie können stattdessen SysUtils.Supports() verwenden, um eine Schnittstelle an eine andere Schnittstelle zu übergeben.

+0

Verstehen, nicht direkt das Problem. Erkenne, was der Compiler sagt und warum es ein Problem für Delphi ist. Ich stimme dem Design nicht zu, aber ich suche nach einem Grund, warum ich mein Design mit den Einschränkungen von Delphi umgehen sollte. Momentan denke ich, dass das Übergeben des Objekts leider der einzige Weg ist. Danke für die Kommentare. – Jason

Verwandte Themen