これは、すべてこの基本インターフェイス定義に基づいている数十のインターフェイスを持つユニットで作業しているため、私にとっては少し不可解です。
type
IDataObject = interface(IInterface)
['{B1B3A532-0E7D-4D4A-8BDC-FD652BFC96B9}']
function This: TDataObject;
end;
ISomeObject = interface(IDataObject)
['{7FFA91DE-EF15-4220-A43F-2C53CBF1077D}']
<Blah>
end;
これは、それらすべてがインターフェイスの背後にあるクラスを返すメソッド 'This' を持っていることを意味します。これは、リストビューなどに入れる必要がある場合がありますが、この質問では、追加の機能を持つジェネリック クラスが必要なので、実際には問題ではありません。派生インターフェイスに適用されます。(派生インターフェイスには独自の GUID があります。) これはジェネリック クラスです。
type
Cast<T: IDataObject> = class(TDataObject)
class function Has(Data: IDataObject): Boolean;
class function Get(Data: IDataObject): T;
end;
複雑すぎないように見えます。クラス メソッドを使用するのは、Delphi がグローバル ジェネリック関数をサポートしていないためです。したがって、私のコードではCast<ISomeObject>.Has(SomeObject)
、オブジェクトが特定のインターフェイスをサポートしているかどうかを確認するために使用したいと考えています。関数は、Get()
可能であれば、オブジェクトを特定の型として返すだけです。したがって、次の実装:
class function Cast<T>.Get(Data: IDataObject): T;
begin
if (Data.QueryInterface(T, Result) <> S_OK) then
Result := nil;
end;
class function Cast<T>.Has(Data: IDataObject): Boolean;
begin
Result := (Data.QueryInterface(T, Result) = S_OK);
end;
そして、これはそれが面倒になるところです!私のコードの他の場所で使用if (Source.QueryInterface(ISomeObject, SomeObject) = 0) then ...
していますが、問題なく動作します。これらの一般的なメソッドでは、ISomeObject
は に置き換えられT
、機能するはずです。しかし、コンパイルを拒否し、次のエラーが発生します。
[dcc64 エラー] DataInterfaces.pas(684): E2010 互換性のない型: 'TGUID' および 'T'
そして、それは迷惑です。これを修正する必要がありますが、システム ユニットのインターフェイス コードを深く掘り下げない限り、適切な解決策を見つけることができません。(多くの異なるプラットフォームで実行する必要があるため、このコードで使用できる唯一のユニットです!)
QueryInterface はパラメーターとして TGUID を想定しているため、エラーは正しいですが、ISomeObject から取得しているようです。では、なぜTからではないのですか?
私はここで不可能なことをしようとしていると思います...
もう少し具体的に言うSource.QueryInterface(ISomeObject, SomeObject)
と、他のユニットを使用しなくても問題なく動作します。そのため、その型がインターフェイスに限定されている場合、ジェネリック型で動作することが期待されます。しかし、そうではなく、ISomeObject を受け入れるのに T を受け入れない理由を知りたいです。
通常のインターフェイス タイプではなくジェネリック タイプで失敗する理由を説明できますか?