Dans Delphi, IUnknown
est déclarée comme:Delphi: Comment implémenter QueryInterface de IUnknown?
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
Note: Le paramètre de sortie est typées
Dans mon TInterfacedObject
descendant je dois gérer QueryInterface
, donc je peux retourner un objet qui prend en charge la demande Interface:
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;
le problème vient sur la ligne:
Obj := (TFooBar.Create(Self) as IFooBar);
Delphi se plaint:
Opérateur non applicable à ce type d'opérande
Il est évident que je ne sais pas comment ou quoi attribuer à un paramètre typéesout
. Je peux essayer des choses au hasard, dans l'espoir que le compilateur: arrêter de se plaindre
Obj := TFooBar.Create(Self);
Obj := Pointer(TFooBar.Create(Self));
Obj := Pointer(TFooBar.Create(Self) as IFooBar);
Ignorant tout le code que j'ai écrit (si nécessaire): comment puis-je mettre QueryInterface
dans un descendant d'objets de TInterfacedObject
?
Le vrai problème que j'ai essayé de résoudre peut se résumer à je veux:
Je veux remplacer les méthodes dans une interface
De la même manière :
TList = class(TObject)
...
function GetItem(Index: Integer): Pointer;
procedure SetItem(Index: Integer; Value: Pointer);
property Items[Index: Integer]: Pointer read GetItem write SetItem;
end;
peut être redéfinies dans une classe descendante:
TStudentList = class(TList)
...
function GetItem(Index: Integer): TStudent;
procedure SetItem(Index: Integer; Value: TStudent);
property Items[Index: Integer]: TStudent read GetItem write SetItem;
end;
je veux donc la même chose avec les interfaces:
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;
Le problème est que la façon dont je dois commencer mon chargement objet avec la mise en œuvre:
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;
Et il n'y a pas seulement les deux méthodes en IFoo
, il y a 6. Et puis si je veux ajouter une autre interface prise en charge:
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;
Et les choses deviennent très lourdes très rapidement.
Je vous encourage également à poser une question sur votre "vrai problème". Cela semble intéressant, et j'ai une vague idée de la façon de le faire (quelque chose à propos de * aggregates * et * conteneurs *). Vous pourriez trouver que vous écrivez plus de code que nécessaire. –
@Rob Kennedy Si vous pouvez penser à un titre utile pour cela, cela susciterait de l'intérêt, je le ferais certainement. Je trouve que sans un bon * crochet *, la question reste sans réponse. Cette question était bonne, parce que la question, telle qu'elle était formulée, avait l'air facile - alors je soutenais des gens qui pensaient pouvoir me donner une éducation facile. D'autre part, vous et Uwe semblent patrouiller pour des questions Delphi :) –