Нужны ли идентификаторы GUID для использования интерфейсов в Delphi?

Официальная документация говорит, что они необязательны. Я знаю, что COM-взаимодействие требует уникального идентификатора для каждого интерфейса, но каждый пример интерфейса, который я вижу, имеет GUID независимо от того, используется ли он с COM или нет? Есть ли польза от включения GUID, если он не будет использоваться с COM?


person Kenneth Cochran    schedule 07.06.2010    source источник


Ответы (2)


Я заметил, что некоторые методы, такие как Supports (для определения соответствия класса к определенному интерфейсу) требуют, чтобы вы определили GUID, прежде чем вы сможете их использовать.

Эта страница подтверждает это следующей информацией:

Примечание. Модуль SysUtils предоставляет перегруженную функцию с именем Supports, которая возвращает значение true или false, когда типы и экземпляры классов поддерживают определенный интерфейс, представленный GUID. Функция Supports используется аналогично Delphi is and как операторы. Существенное отличие состоит в том, что функция Supports может принимать в качестве правильного операнда либо GUID, либо тип интерфейса, связанный с GUID, тогда как is и as принимают имя типа. Дополнительные сведения о is и as см. в разделе Ссылки на классы.

Вот интересная информация об интерфейсах, в которой говорится:

Почему интерфейс должен быть однозначно идентифицируемым? Ответ прост: потому что классы Delphi могут реализовывать несколько интерфейсов. Когда приложение работает, должен быть механизм, который получит указатель на соответствующий интерфейс из реализации. Единственный способ узнать, реализует ли объект интерфейс, и получить указатель на реализацию этого интерфейса — через идентификаторы GUID.

Выделение добавлено в обе цитаты.

Прочитав всю эту статью, вы также поймете, что QueryInterface (для которого требуется GUID ) используется за кулисами по таким причинам, как подсчет ссылок.

person Senseful    schedule 07.06.2010
comment
Кроме того, стоит отметить, что попытка использовать приведение типов is или as с интерфейсом включает в себя один из этих вызовов (не помню какой) под капотом, поэтому для этого вам также понадобится GUID. - person Mason Wheeler; 07.06.2010
comment
Итак, краткий ответ: хотя идентификаторы GUID являются необязательными, их использование не ограничивает то, что вы можете делать с интерфейсами. - person Kenneth Cochran; 08.06.2010
comment
Необходимость использования функции Supports пока единственная причина, по которой я определяю GUID для интерфейсов. - person Edwin Yip; 16.04.2012
comment
Единственный способ узнать, реализует ли объект интерфейс, и получить указатель на реализацию этого интерфейса — через GUID. Почему бы просто не запросить методы объекта и не проверить, присутствуют ли в объекте методы с такими именами? Старая добрая утиная печать? Вы не увидите эту чепуху с GUID на других языках. - person alcalde; 08.06.2014

Только если вам нужно, чтобы ваш интерфейс был совместим с COM.

К сожалению, это также включает в себя использование операторов is, as и функций QueryInterface, Supports — отсутствие которых довольно ограничивает. Таким образом, хотя это и не является строго обязательным, вероятно, проще использовать GUID. В противном случае у вас останется только довольно упрощенное использование:

type
  ITest = interface
    procedure Test;
  end;

  ITest2 = interface(ITest)
    procedure Test2;
  end;

  TTest = class(TInterfacedObject, ITest, ITest2)
  public
    procedure Test;
    procedure Test2;
  end;

procedure TTest.Test;
begin
  Writeln('Test');
end;

procedure TTest.Test2;
begin
  Writeln('Test2');
end;

procedure DoTest(const Test: ITest);
begin
  Test.Test;
end;

procedure DoTest2(const Test: ITest2);
begin
  Test.Test;
  Test.Test2;
end;

procedure Main;
var
  Test: ITest;
  Test2: ITest2;
begin
  Test := TTest.Create;
  DoTest(Test);
  Test := nil;

  Test2 := TTest.Create;
  DoTest(Test2);
  DoTest2(Test2);
end;
person Ondrej Kelle    schedule 07.06.2010
comment
Это не правильно; см. ответ @eagle. Единственный способ, которым вы можете использовать не COM-интерфейс без GUID, — это небезопасное жесткое приведение. - person Craig Stuntz; 07.06.2010
comment
Если в примере, который я добавил выше, есть что-то небезопасное, пожалуйста, дайте мне знать, спасибо. - person Ondrej Kelle; 07.06.2010
comment
@Craig: я не уверен, что небезопасные жесткие приведения существуют даже для интерфейсов, поскольку компилятору все еще нужен какой-то способ найти таблицу интерфейсов для используемого интерфейса. - person Mason Wheeler; 08.06.2010
comment
@ Мейсон, они делают. Раньше это был единственный способ использовать IProviderSupport. Исходный код VCL делал это, по крайней мере, в эпоху D6. - person Craig Stuntz; 08.06.2010
comment
@TOndrej, ваш код безопасен, потому что вы никогда не переходите на несвязанный интерфейс (множественное наследование, по сути), что является значительной частью причины, по которой вы используете интерфейсы. Представьте себе IFoo без отношения подтипа к ITest. Как преобразовать ссылку ITest в ссылку IFoo , предполагая, что тип реализации поддерживает оба варианта. Вам нужен GUID, чтобы сделать это безопасно. - person Craig Stuntz; 08.06.2010