пятница, 4 апреля 2014 г.

Коротко. Об особенностях Supports

Не буду заниматься анализом или "разжёвыванием".

Просто приведу пример.

Просто, "чтоб вы знали".

Вот такой код:

type
 ISomeInterface = interface
  procedure SomeMethod;
 end;//

 TA = class(TObject, ISomeInterface {IUnknown тут СПЕЦИАЛЬНО опущен})
  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
 if not Supports(B, ISomeInterface, l_B) then
  Assert(false);
 l_B.SomeMethod; // - в консоли видим A, а "хотелось бы" - C
end;

Хотя "всё очевидно". Смотрим на код:

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;

Почему я это пишу?

Просто потому, что я видел людей, которые сильно удивляются этому.

Для тех кто хочет "откомментировать" скажу - "я не из их числа".

Хотя... И сам "нажирался"...

2 комментария:

  1. Извините но я не понимаю как мы ожидаем С. Если это метод класса TC. Мы же даже объект не создаем ?

    ОтветитьУдалить
  2. Ответил тут - http://programmingmindstream.blogspot.ru/2014/04/supports_4.html

    ОтветитьУдалить