2013-02-18 15 views
9

Ich brauche eine Klasse implementierende Schnittstelle ohne Referenzzählung. Ich tat folgendes:Casting-Objekt zu Interface-Typ ohne TInterfacedObject als Basisklasse

IMyInterface = interface(IInterface) 
     ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
     procedure InterfaceMethod; 
    end; 

    TMyClass = class(TObject, IMyInterface) 
    protected 
     function _AddRef: Integer;stdcall; 
     function _Release: Integer;stdcall; 
     function QueryInterface(const IID: TGUID; out Obj): HResult;stdcall; 
    public 
     procedure InterfaceMethod; 
    end; 

    procedure TMyClass.InterfaceMethod; 
    begin 
     ShowMessage('The Method'); 
    end; 

    function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult; 
    begin 
     if GetInterface(IID, Obj) then 
      Result := 0 
     else 
      Result := E_NOINTERFACE; 
    end; 

    function TMyClass._AddRef: Integer; 
    begin 
     Result := -1; 
    end; 

    function TMyClass._Release: Integer; 
    begin 
     Result := -1; 
    end; 

Fehlende Referenzzählung funktioniert gut. Aber meine Sorge ist, dass ich nicht TMyClass-IMyInterface mit as Betreiber werfen können:

var 
    MyI: IMyInterface; 
begin 
    MyI := TMyClass.Create as IMyInterface; 

mir gegeben

[DCC Error] E2015 Operator nicht anwendbar auf diese Operandtyp

Die Problem verschwindet, wenn TMyClass von TInterfacedObject abgeleitet wird - dh ich kann ein solches Casting ohne Compilerfehler machen. Offensichtlich möchte ich TInterfacedObject nicht als Basisklasse verwenden, da dies meine Klassenreferenz zählen würde. Warum ist ein solches Casting nicht erlaubt und wie könnte man es umgehen?

+0

Sie könnten bessere Ergebnisse erzielen, wenn Sie Ihrer Schnittstellenkennung eine GUID hinzufügen. Fügen Sie nach der Zeile "= interface" eine neue Zeile hinzu und drücken Sie Strg-Shft-G. 'as',' GetInterface' und 'supports' usw. müssen in der Lage sein, die Schnittstelle nach GUID zu identifizieren, um zu funktionieren. –

+0

Sie haben meine Post nicht sorgfältig gelesen. Wenn ich von TInterfacedObject ableite funktioniert es. GUID hat hier nichts zu tun. Sie benötigen GUID nur, um mit COM zu arbeiten. –

+0

Hmm, welche Delphi Version? –

Antwort

14

Der Grund, warum Sie in Ihrem Code as nicht verwenden können, ist, dass Ihre Klasse IInterface in ihrer Liste der unterstützten Schnittstellen nicht explizit auflistet. Obwohl Ihre Schnittstelle von IInterface stammt, wird diese Klasse von Ihnen nicht unterstützt, es sei denn, Sie listen diese Schnittstelle auf.

So ist die triviale Lösung ist Ihre Klasse wie folgt zu erklären:

TMyClass = class(TObject, IInterface, IMyInterface) 

Der Grund, dass Ihre Klasse IInterface implementieren muss, ist das ist, was der Compiler auf setzt, um den as Guss umzusetzen.

Der andere Punkt, den ich möchte, ist, dass Sie im Allgemeinen vermeiden sollten, Schnittstellenvererbung zu verwenden. Im großen und ganzen dient es wenig Zweck. Einer der Vorteile der Verwendung von Schnittstellen besteht darin, dass Sie nicht die einzige Vererbungsbeschränkung haben, die mit der Implementationsvererbung einhergeht.

Aber in jedem Fall, alle Delphi-Schnittstellen so in Ihrem Fall gibt es keinen Punkt, der das angibt. Ich würde Ihre Schnittstelle wie folgt erklären:

IMyInterface = interface 
    ['{B84904DF-9E8A-46E0-98E4-498BF03C2819}'] 
    procedure InterfaceMethod; 
end; 

Allgemeiner gesagt sollten Sie sich bemühen, keine Vererbung mit Schnittstellen zu verwenden. Wenn Sie diesen Ansatz wählen, werden Sie weniger Kopplung fördern und das führt zu größerer Flexibilität.

+0

Schnittstellenvererbung ist ** nicht ** Implementierungsvererbung. Auch jede Schnittstelle in Delphi ist von "IInterface" abgeleitet. Der letzte Satz ist unklar. – kludg

+0

@Serg Diese Schnittstelle Vererbung ist ** nicht ** Umsetzung Vererbung ist genau der Punkt, den ich versuche zu machen. Ich werde versuchen, es aufzuräumen. –

+1

Danke für die Erklärung. Jetzt finde ich es klar und offensichtlich :) –

Verwandte Themen