2013-02-18 9 views
9

参照カウントを持たないクラスを実装するクラスが必要です。私は次のようでした:参照カウントの基本型としてTInterfacedObjectを持たないインターフェイス型にオブジェクトをキャスト

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; 

欠如は、正常に動作します。私は

[DCCのエラー] E2015演算子このオペランドのタイプには適用されません

与えられています

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

:しかし、私の懸念は、私がas演算子を使用してIMyInterfaceTMyClassをキャストすることができないということですTMyClassTInterfacedObjectから派生したときに問題が解消しました。つまり、コンパイラエラーなしでこのようなキャストを実行できます。明らかに、TInterfacedObjectをベースクラスとして使用したくないので、クラス参照をカウントします。なぜこのようなキャスティングは禁止されているのですか?

+0

インターフェイス宣言にGUIDを追加すると、より良い結果が得られる場合があります。 '= interface'行の後ろに新しい行を追加し、Ctrl-Shft-Gを押します。 'as'、' GetInterface'や 'supports'などは、動作するためにGUIDによってインタフェースを識別できる必要があります。 –

+0

あなたは自分の投稿を慎重に読まなかった。私はTInterfacedObjectから派生したときに動作します。 GUIDはここでは何もしません。 COMで操作するには、GUIDが必要です。 –

+0

ええと、どのDelphiのバージョン? –

答えて

14

asをコードに使用できない理由は、クラスがサポートされているインターフェイスの一覧に明示的にIInterfaceを記載していないためです。あなたのインターフェイスはIInterfaceから派生していますが、実際にインターフェイスをリストしていない限り、クラスはサポートしていません。

ので、些細な修正は、このようなあなたのクラスを宣言することです:あなたのクラスがIInterfaceを実装する必要があり

TMyClass = class(TObject, IInterface, IMyInterface) 

理由は、コンパイラがasキャストを実装するために頼っているものです。

私が作っておきたいもう一つのポイントは、一般的にインターフェイスの継承を使用しないことです。全体的に見ると、ほとんど役に立たない。インターフェイスを使用する利点の1つは、実装の継承に伴う単一の継承の制約がないことです。

いずれにしても、すべてのDelphiインターフェイスautomatically inherit from IInterfaceのように、あなたの場合はそれを指定する必要はありません。

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

より広義には、インターフェイスで継承を使用しないようにする必要があります。このアプローチをとることで、カップリングが少なくなり、柔軟性が向上します。

+0

インタフェースの継承は**実装の継承ではありません**。また、Delphiのどのインタフェースも 'IInterface'から派生しています。最後の文は不明です。 – kludg

+0

@Sergそのインタフェースの継承は**実装ではありません**継承は私が作ろうとしているポイントです。私はそれをクリアしようとします。 –

+1

ありがとうございます。今私はそれが明確で分かりやすいと感じる:) –