質問

Delphiでは、IUnknownは次のように宣言されています。

function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
.

注:出力パラメータは解除されていません

私のTInterfacedObjectの子孫では、QueryInterfaceを処理する必要があるため、要求されたインターフェイスをサポートするオブジェクトを返すことができます。

function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
   if IsEqualGUID(IID, IFooBar) then
   begin
      Obj := (TFooBar.Create(Self) as IFooBar);
      Result := S_OK;
   end
   else
      Result := inherited QueryInterface(IID, {out}Obj);
end;
.

問題は行に付属しています:

Obj := (TFooBar.Create(Self) as IFooBar);
.

Delphiは以下のとおりです。

オペレータこのオペランドタイプ

には適用されません

明らかに私は untyped outパラメータにどのように割り当てられているかを知りません。私はランダムに物事を試みることができます、コンパイラが文句を言うのをやめることを期待して:

Obj := TFooBar.Create(Self);

Obj := Pointer(TFooBar.Create(Self));

Obj := Pointer(TFooBar.Create(Self) as IFooBar);
.

私が書いたコードをすべて無視する(必要な場合):QueryInterfaceからのオブジェクトの子孫にTInterfacedObjectを実装するにはどうすればよいですか?


私が解決しようとしていた本当の問題は私がしたいと思うように煮ることができます:

インタフェース

のメソッドをオーバーライドしたい

同じ方法で:

TList = class(TObject)
...
   function GetItem(Index: Integer): Pointer; 
   procedure SetItem(Index: Integer; Value: Pointer);
   property Items[Index: Integer]: Pointer read GetItem write SetItem;
end;
.

は子孫クラスでオーバーライドできます。

TStudentList = class(TList)
...
   function GetItem(Index: Integer): TStudent; 
   procedure SetItem(Index: Integer; Value: TStudent);
   property Items[Index: Integer]: TStudent read GetItem write SetItem;
end;
.

インターフェイスで同じにしたい:

IFoo = interface(IUnknown)
...
   function GetItem(Index: Variant): Variant; 
   procedure SetItem(Index: Variant; Value: Variant);
   property Items[Index: Variant]: Variant read GetItem write SetItem;
end;

IFooGuidString = interface(IFoo)
...
   function GetItem(Index: TGUID): string ; 
   procedure SetItem(Index: TGUID; Value: string );
   property Items[Index: TGUID]: string read GetItem write SetItem;
end;
.

問題は、私が実装オブジェクトの読み込みを行う方法が次のとおりです。

TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
   function IFoo.GetItem = FooGetItem;
   procedure IFoo.SetItem = FooSetItem;
   function FooGetItem(Index: Variant): Variant; 
   procedure FooSetItem(Index: Variant; Value: Variant);

   function IFooGuidString.GetItem = FooGuidStringGetItem;
   procedure IFooGuidString.SetItem = FooGuidStringSetItem;
   function FooGuidStringGetItem(Index: TGUID): string ; 
   procedure FooGuidStringSetItem(Index: TGUID; Value: string );
end;
.

IFooには2つのメソッドだけではなく、6があります。その場合は、サポートされている別のインターフェイスを追加したい場合

IFooInt64String = interface(IFoo)
...
   function GetItem(Index: Int64): string ; 
   procedure SetItem(Index: Int64; Value: string );
   property Items[Index: Int64]: string read GetItem write SetItem;
end;


TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
   function IFoo.GetItem = FooGetItem;
   procedure IFoo.SetItem = FooSetItem;
   function FooGetItem(Index: Variant): Variant; 
   procedure FooSetItem(Index: Variant; Value: Variant);

   function IFooGuidString.GetItem = FooGuidStringGetItem;
   procedure IFooGuidString.SetItem = FooGuidStringSetItem;
   function FooGuidStringGetItem(Index: TGUID): string ; 
   procedure FooGuidStringSetItem(Index: TGUID; Value: string );

   function IFooInt64String.GetItem = FooInt64StringGetItem;
   procedure IFooInt64String.SetItem = FooInt64StringSetItem;
   function FooInt64StringGetItem(Index: Int64): string ; 
   procedure FooInt64StringSetItem(Index: Int64; Value: string );
end;
.

と物事は非常に速く扱いにくいです。

他のヒント

ここでの規則を壊すというローブの発言の上で、この構成要素でも成功することができます:

function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
   if IsEqualGUID(IID, IFooBar) then
      Result := TFooBar.Create(Self).QueryInterface(IID, obj)
   else
      Result := inherited QueryInterface(IID, {out}Obj);
end;
.

私はこれを調査しなかったが、あなたは参照カウントでいくつかの問題を得るかもしれません...

System.PASでのToBject.GetInterfaceの実装に基づいてこれを推奨します。

  Pointer(Obj) := TFooBar.Create(Self);
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top