среда, 5 августа 2015 г.

Briefly. Peculiarities of Supports

Original in Russian: http://programmingmindstream.blogspot.ru/2014/04/supports.html

I will not go in for analysis or “spoon-feeding”.

I’ll just give an example.

Just “for your information”.

The code:

type
 ISomeInterface = interface
  procedure SomeMethod;
 end;//
 
 TA = class(TObject, ISomeInterface {IUnknown is omitted FOR PURPOSE here})
  function _AddRef: Integer;
  function _Release: Integer;
  function QueryInterface(const anID: TGUID; out anObj): hResult; virtual; 
  procedure SomeMethod;
 end;//TA
 
 TB = class(TA)
  function QueryInterface(const anID: TGUID; out anObj): hResult; override;
 end;//TB
 
 TC = class(TIntefacedObject, ISomeInterface)
  procedure SomeMethod;
 end;//TC
 
...
 
function TA._AddRef: Integer;
begin
 Result := -1;
end;
 
function TA._Release: Integer;
begin
 Result := -1;
end;
 
function TA.QueryInterface(const anID: TGUID; out anObj): hResult;
begin
 if Self.GetInterface(anID, anObj) then
  Result := S_Ok
 else
  Result := E_NoInterface;
end;
 
procedure TA.SomeMethod;
begin
 Write('A');
end;
 
function TB.QueryInterface(const anID: TGUID; out anObj): hResult;
begin
 if IsEqualGUID(anID, ISomeInterface) then
 begin
  Result := S_Ok;
  ISomeInterface(Obj) := TC.Create;
 end//IsEqualGUID(anID, ISomeInterface)
 else
  Result := inherited QueryInterface(anID, Obj);  
end;
 
procedure TC.SomeMethod;
begin
 Write('C');
end;
 
...
var
 l_A : ISomeInterface;
 l_B : ISomeInterface;
begin
 A := TA.Create;
 B := TB.Create;
 if not Supports(A, ISomeInterface, l_A) then
  Assert(false);
 l_A.SomeMethod; // - A is seen in console
 if not Supports(B, ISomeInterface, l_B) then
  Assert(false);
 l_B.SomeMethod; // - A is seen in console, and we need C
end;

Though “it is obvious”. Have a look at the code:

function Supports(const Instance: TObject; const IID: TGUID; out Intf): Boolean;
var
  LUnknown: IUnknown;
begin
  Result := (Instance <> nil) and
            ((Instance.GetInterface(IUnknown, LUnknown) and Supports(LUnknown, IID, Intf)) or
             Instance.GetInterface(IID, Intf));
end;

Why do I write?

The reason is, I have seen people who are very amazed by it. (I am not one of them.)

Though... I “pigged out”, too.

Комментариев нет:

Отправить комментарий