2016-05-24 8 views
2

クラスが実装しているインタフェースを定義する汎用パラメータを持つことは可能ですか?
それとも誰もがDelphiはこれを許可しない理由を説明、持っていない(または私はちょうどそれが間違ってやっているの?):汎用クラスが実装しているインタフェースを定義する汎用パラメータ

TInterfacedMyWrapper<T: IInterface> = class(TMyWrapper, T) 
    function PropGetIntf(): T; 
    property Intf: T read PropGetIntf implements T; 
end; 

これは、次のエラーを得られます。

  • E2205: Interface type required
  • E2259: Implements clause only allowed for properties of class or interface type

これは私の回避策です。

TInterfacedMyWrapper<T: IInterface> = class(TMyWrapper) 
    function PropGetIntf(): T; 
    property Intf: T read PropGetIntf; 
end; 

TIFooMyWrapper = class(TInterfacedMyWrapper<IFoo>, IFoo) 
    property Intf: IFoo read PropGetIntf implements IFoo; 
end; 

しかし、これにより、すべてのインターフェイスに別のクラスを定義する必要があります。 I'ldではなく書くのが好き:

TInterfacedMyWrapper<IFoo>.Create(CompToWrap); 



編集(私の目標を説明するためにいくつかのより多くの文脈 - 私はそれがあまりにも混乱していないことを願う...):

私は複数のクラスを持っていますTFooCompから派生したもので、変更することはできません。そして私はTBarBaseを継承するラッパークラスTMyWrapperを持っています。 TBarBaseは変更できません。 TMyWrapperTFooComp(アダプタパターンの種類)のラッパーです。

すべてTFooComp -derivedクラスがインターフェイスを公開することがあります。私が手に入れたいのは、TInterfacedMyWrapperもそのインターフェイスを公開しており、 ラップされたTFooCompにそれを委譲しているということです。

これが何らかの形で働いている:

constructor TMyWrapper.CreateNew(AOwner: TComponent; FooClass: TFooClass); 
begin 
    FWrappedFooComp := FooClass.Create(Self); 
    //... 
end; 

//... 

function TInterfacedMyWrapper<T>.PropGetIntf(): T; 
begin 
    //see http://stackoverflow.com/questions/4418278/use-of-supports-function-with-generic-interface-type 
    if not Supports(FWrappedFooComp, GetTypeData(TypeInfo(T))^.Guid, Result) then 
     raise Exception.Create('Interface not implemented'); 
end; 

しかし、すべてのTFooComp由来のクラスIは、(ひとつの宣言で)独自のラッパークラスを作成する必要があります。私は使用することができます

TWrappedFooXxx = class(TInterfacedMyWrapper<IXxx>, Ixxx) 
    property Intf: IXxx read PropGetIntf implements IXxx; 
end; 

次のようにします。

Result := TWrappedFooXxx.CreateNew(Owner, TFooXxx); 
Result.DoSomething(); 
(Result as IXxx).DoSomeMore(); 

独自のラッパーcを作成する必要性私は避けようとしています。

Result := TInterfacedMyWrapper<IXxx>.CreateNew(Owner, TFooXxx); 
Result.DoSomething(); 
(Result as IXxx).DoSomeMore(); 
+0

いくつかのもののタイプを推測する必要がないので、小さくても完全なサンプルプログラムが良いでしょう( 'TInterfacedObject'から' TBarBase'を継承するかどうか、最後の2つのタイプは 'Result'です)スニペット) –

+0

@StefanGlienke実際のコードは、コードです、とにかく公開したいと思います。私は出版前にこの質問をチェックしたかっただけです。私はこの質問をある意味で投稿しようとしました、それは狭くないことです。しかし、あなたは正しいです。実際のコードをクリーンアップし、公開し、リンクを提供し、ここでサンプルプログラムを提供します。 (あなたの質問について: 'TBarBase'と' TMyWrapper'は 'TComponent'から継承し、' IInterface'を実装します.'Result'の型は、TMyWrapperから派生した 'CreateNew'によって決定されます)。 – yonojoy

答えて

1

Delphiはこれを許可しない理由:私はむしろだけ書くでしょうか?

これはC++テンプレートではないためです。 Delphiのコンパイラは、クラスが実装しているインタフェースを知っている必要があります(汎用ですが)。しかし、この場合は、まだ知られていないインターフェースを実装しようとしているのでできません。

+0

OK、これは、私が使用した構文がなぜ機能しないのかを説明しています(私はあなたの主張の "公式"参照を見つけようとしましたが、見つけられませんでした)。しかし、「TVirtualInterface」の存在は、コンパイル時にクラスに知られていないインターフェースを実装することが完全に不可能ではないと私に信じさせています。 ) 'TtoterfacedMyWrapper .Create(CompToWrap)as IFoo'も持っているといいですよね。) – yonojoy

+1

' CompToWrap'は明らかに 'T'型ではないので、あなたが達成しようとしていたのは不思議です。 'PropGetIntf'でラップされたインスタンスを返すだけで、カスタムコードを追加することはできません(デコレータパターンのように)。あなたの質問にもう少しコンテキストを提供してください。 –

+0

彼は、インターフェイス用に宣言されたすべてのメソッドを持つクラスにインターフェイスサポートを動的に追加しようとしていますが、そのインターフェイスをサポートすると宣言しませんでした。 'TWrap .Create(TStringList.Create)'のようなものです(TStringListはIUnknownをサポートしていませんが、あなたはアイデアを得ていますか?) –

関連する問題