1

これは、すべてこの基本インターフェイス定義に基づいている数十のインターフェイスを持つユニットで作業しているため、私にとっては少し不可解です。

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 を受け入れない理由を知りたいです。
通常のインターフェイス タイプではなくジェネリック タイプで失敗する理由を説明できますか?

4

1 に答える 1