четверг, 31 октября 2013 г.

О да! Про supports.

Множество задач использования Supports (QueryInterface) сводятся примерно к следующему:
IMemoryPool = interface
end;//IMemoryPool

IString = interface(SomeAncestor1)
end;//IString

IMemoryStream = interface(SomeAncestor2)
end;//IMemoryStream

DoString(aString : IString);
begin
 if Supports(aString, IMemoryPool, l_Pool) then
 ... do something with l_Pool
end;

DoStream(aStream : IMemoryStream );
begin
 if Supports(aString, IMemoryPool, l_Pool) then
 ... do something with l_Pool
end;

хотя можно написать так:

IMemoryPool = interface
end;//IMemoryPool

IString = interface(SomeAncestor1{, implements IMemoryPool })
 function AsPool : IMemoryPool;
end;//IString

IMemoryStream = interface(SomeAncestor2{, implements IMemoryPool })
 function AsPool : IMemoryPool;
end;//IMemoryStream

DoString(aString : IString);
begin
 aString.AsPool
 ... do something with AsPool
end;

DoStream(aStream : IMemoryStream );
begin
 aStream.AsPool
 ... do something with AsPool
end;

-- второе - понятное дело - эффективнее.

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

  1. Это ведь подойдет только в каких-то частных узких случаях. У тебя получается, что IMemoryStream обязан имплементировать еще и IMemoryPool. То есть интерфейсы оказываются очень жестко связаными между собой.

    ОтветитьУдалить
  2. Роман, конечно в "частных случаях". Всё в ЭТОМ МИРЕ - частные случаи. По крайней мере лично "сферические кони" - не встречались.

    "Обязан" конечно. О ТОМ и речь. Что не надо ЗЛОУПОТРЕБЛЯТЬ Supports и QueryInterface. Там где ЯВНО можно вернуть то, ЧТО подразумевается. А МНОГИЕ - именно ЗЛОУПОТРЕБЛЯЮТ. Во славу всё тех же "сферических коней".

    ОтветитьУдалить
    Ответы
    1. "То есть интерфейсы оказываются очень жестко связаными между собой."
      --- и это в ОГРОМНОМ количестве случаев - ХОРОШО.

      Удалить
  3. Только дело в том, что почти для всех таких "частных случаев" - у меня написан шаблон кодогенерации.

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