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は文句を言います:
このオペランドタイプに適用できない演算子
明らかに、型指定されていない 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;
そして、には2つのメソッドだけでなく、IFoo
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;
そして、物事は非常に速く扱いにくくなります。