Глобально-уникальный идентификатор интерфейса

Интерфейс является особым типом данных: он может быть реализован в одной программе, а использоваться из другой. Для этого нужно обеспечить идентификацию интерфейса при межпрограммном взаимодействии. Понятно, что программный идентификатор интерфейса для этого не подходит - разные программы пишутся разными людьми, а разные люди подчас дают одинаковые имена своим творениям. Поэтому каждому интерфейсу выдается своеобразный <паспорт> - глобально-уникальный идентификатор (Globally Unique Identifier - GUID).

Глобально-уникальный идентификатор - это 16-ти байтовое число, представленное в виде заключенной в фигурные скобки последовательности шестнадцатеричных цифр:

{DC601962-28E5-4BF7-9583-0CE22B605045}

В среде Delphi глобально-уникальный идентификатор описывается типом данных TGUID:

type
  PGUID = ^TGUID;
  TGUID = packed record
    D1: Longword;
    D2: Word;
    D3: Word;
    D4: array[0..7] of Byte;
  end;

Константы с типом TGUID разрешено инициализировать строковым представлением глобально-уникального идентификатора. Компилятор сам преобразует строку в запись с типом TGUID. Пример:

const
  InterfaceID: TGUID = '{DC601962-28E5-4BF7-9583-0CE22B605045}';

Если глобально-уникальный идентификатор назначается интерфейсу, то он записывается после ключевого слова interface и заключается в квадратные скобки, например:

type
  IInterface = interface
    ['{00000000-0000-0000-C000-000000000046}']
    ...
  end;

В будущем нашему интерфейсу ITextReader понадобится глобально-уникальный идентификатор. Но как его выбрать так, чтобы он оказался уникальным? Очень просто - нажмите в редакторе кода комбинацию клавиш Ctrl+Shift+G.

type
  ITextReader = interface
    ['{DC601962-28E5-4BF7-9583-
0CE22B605045}'] // Результат нажатия Ctrl+Shift+G
    ...
  end;

Генерация глобально-уникальных идентификаторов осуществляется системой Windows по специальному алгоритму, в котором задействуется адрес сетевого адаптера, текущее время и генератор случайных чисел. Можете смело полагаться на уникальность всех получаемых идентификаторов.

Наличие глобально-уникального идентификатора в описании интерфейса не является обязательным, однако использование интерфейса без такого идентификатора ограничено, например, запрещено использовать оператор as для преобразования одних интерфейсов в другие.

Если у интерфейса есть глобально-уникальный идентификатор, то программный идентификатор интерфейса можно использовать там, где ожидается тип данных TGUID, например:

const 
  IID_ITextReader: TGUID = '{DC601962-28E5-4B
F7-9583-0CE22B605045}';

function TestInterface(const IID: TGUID): Boolean;

begin 
  ...
  TestInterface(ITextReader);
  // эквивалентно
  TestInterface(IID_ITextReader);
  ...
end;

 

Яндекс цитирования