2013-05-14 14 views
6

I持って、次のコードDelphiのインターフェイス汎用関数 - 回避策はありますか?

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

コンパイルするときに受信したコンパイラエラーを回避する方法はありますか?

「[DCCのエラー] Delphi.Mocks.pas(123):E2535インタフェースのメソッドは、パラメータ化メソッドあってはならない」

を基本的に私は、このインタフェースが回されていて、それをオフにキャストできるようにしたいと思い、キャストする型を渡して、その型を返します。私はクラスでこれを達成できますが、インターフェイスを回ることを好むでしょう。

追加情報:

は、新たに要求されたキャストは、新しい仮想インタフェースを作成することができるようCastAsが、ここでうまく機能

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; 

私は以下のクラスを持っていると言います。今、私はこのクラスをその罰金の周りに渡したいと思っています。しかし、私がインターフェイスとしてそれを必要とする場合、すなわちTInterfaceProxy<T> = class(TBaseProxy<T>, IProxy<T>)それは理解できません。それに同意しないで、理解してください。

したがって、どのように私はCastAs関数を呼び出すことができるように、タイプ(任意のインターフェイスタイプ)を渡し、そこから仮想インターフェイスを作成できるようにこの制限を回避しますか?

答えて

12

インタフェースでは、コンパイラが述べているように、汎用のパラメータ化されたメソッドをサポートしていません。

基本的な制限であるため、回避策はありません。クラス内のパラメータ化されたメソッドは、インスタンス化ごとに1つのメソッドをクラスに追加することによって実装されます。それは具体的なものなのでクラスのために働くが、インタフェースのために実行可能ではない。これは、インターフェイスが関数のテーブルであり、そのテーブルのサイズは、コード内のどこかに存在する汎用メソッドのインスタンス化によって異なることはありません。同様の理由から、汎用メソッドは仮想または動的にすることはできません。

あなたの質問のコードは少しでも間違っています。あなたは書きました:

function CastAs<I : IInterface> : IInterface; 

が、私はあなたが意味確信している:いずれの場合で

function CastAs<I : IInterface> : I; 

が、それは不可能です。 1つの選択肢は、代わりにクラスを使用することです。私はこれがバインドであることに同意します。

あなたがインターフェイスでそれをしたい場合は、あなたができる最善のは、次のとおりです。

function CastAs(const IID: TGUID): IInterface; 

しかし、あなたはこのようにそれを呼び出す必要があるだろう:

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

やや汚い感じています。

あなたの毒を選んでください!

+0

ありがとうございます。私はTGUIDが通過するために行って、それと一緒に生きなければならないと信じています。また、クラスを外部に公開しますが、インターフェイス "function CastAs(const IID:TGUID):IInterface;"内部。私は "あなたの言語にプログラムすることができます"ということを望みます。http://programmers.stackexchange.com/questions/2777/what-are-the-key-points-of-code-complete – Jason

+0

また、 function CastAs :I; 'コードをコピーしている間違い。 – Jason

5

エラーメッセージが示すように、インターフェイス内のメソッドはGenericパラメータを持つことができません。コンパイラは、単にそれをサポートしていない、これは、として記載されて:界面における

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

パラメータ化方法

パラメータ化された方法(型パラメータで宣言されたメソッドが)内で宣言することはできませんインタフェース。

つまり、CastAsメソッドは、インターフェイスタイプで宣言されているため、無効です。一方、そのような方法はまず必要ありません。代わりに1つのインターフェイスを別のインターフェイスにキャストする場合はSysUtils.Supports()を使用できます。

+0

理解してください。直接問題はありません。コンパイラが何を言っているのか、それがデルファイにとってなぜ問題なのかを理解してください。設計に同意しないでください。しかし、Delphiの限界を克服して設計を行う理由を探しています。現在、私はオブジェクトを渡すことが悲しいことに唯一の方法だと思っています。コメントありがとう。 – Jason

関連する問題