Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Глобально-уникальный идентификатор интерфейсаСодержание книги
Поиск на нашем сайте
Интерфейс является особым типом данных: он может быть реализован в одной программе, а использоваться из другой. Для этого нужно обеспечить идентификацию интерфейса при межпрограммном взаимодействии. Программный идентификатор интерфейса для этого не подходит – разные программы пишутся разными людьми, а разные люди подчас дают одинаковые имена своим творениям. Поэтому каждому интерфейсу выдается своеобразный «паспорт» — глобально-уникальный идентификатор (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 и заключается в квадратные скобки, например: IInterface = interface ['{00000000-0000-0000-C000-000000000046}'] ... end;
В будущем нашему интерфейсу ITextReader понадобится глобально-уникальный идентификатор. Но как его выбрать так, чтобы он оказался уникальным? Очень просто – нажмите в редакторе кода комбинацию клавиш Ctrl+Shift+G. Генерация глобально-уникальных идентификаторов осуществляется системой Windows по специальному алгоритму, в котором задействуется адрес сетевого адаптера, текущее время и генератор случайных чисел. Наличие глобально-уникального идентификатора в описании интерфейса не является обязательным, однако использование интерфейса без такого идентификатора ограничено, например, запрещено использовать оператор as для преобразования одних интерфейсов в другие. Если у интерфейса есть глобально-уникальный идентификатор, то программный идентификатор интерфейса можно использовать там, где ожидается тип данных TGUID, например: Const IID_ITextReader: TGUID = '{DC601962-28E5-4BF7-9583-0CE22B605045}'; Function TestInterface(constIID: TGUID): Boolean; Beginп ... TestInterface(ITextReader); // эквивалентно TestInterface(IID_ITextReader); ... end;
Совместимость интерфейсов и классов Совместимость интерфейсов подчиняется определенным правилам. Если интерфейс создан расширением уже существующего интерфейса: IExtendedTextReader = interface(ITextReader) то интерфейсной переменной базового типа может быть присвоено значение интерфейсной переменной производного типа, но не наоборот. Любая интерфейсная переменная совместима с типом данных IInterface – прародителем всех интерфейсов. Интерфейсной переменной можно присвоить значение объектной переменной при условии, что объект (точнее его класс) реализует упомянутый интерфейс:
Var Intf: ITextReader; // интерфейсная переменная Obj: TTextReader; // объектная переменная Begin Intf:= Obj; // В переменную Intf копируется ссылка на объект Obj end;
Такая совместимость сохраняется в производных классах. Если класс реализует некоторый интерфейс, то и все его производные классы совместимы с этим интерфейсом. Однако если класс реализует производный интерфейс, то это совсем не означает, что он совместим с базовым интерфейсом. Для совместимости с базовым интерфейсом нужно реализовать этот интерфейс явно:
ITExtendedTextReader = class(TInterfacedObject, ITextReader, IExtendedTextReader);
Исключением из только что описанного правила является совместимость всех снабженных интерфейсами объектов с интерфейсом IInterface.
Получение интерфейса через другой интерфейс
Через интерфейсную переменную у объекта всегда можно запросить интерфейс другого типа. Для этого используется оператор as, например: Var Intf: IInterface; Begin ... With Intf as ITextReader do Active:= True; ... end;
Если объект действительно поддерживает запрашиваемый интерфейс, то результатом является ссылка соответствующего типа. Если же объект не поддерживает интерфейс, то возникает исключительная ситуация EIntfCastError. В действительности оператор as преобразуется компилятором в вызов метода QueryInterface: Var Intf: IInterface; IntfReader: ITextReader; ... IntfReader:= Intf asITextReader; // Intf.QueryInterface(ITextReader, IntfReader);
Напомним, что метод QueryInterface описан в интерфейсе IInterface и попадает автоматически во все интерфейсы. Стандартная реализация этого метода находится в классе TInterfacedObject. Представление интерфейса в памяти Интерфейс по сути выступает дополнительной таблицей виртуальных методов, ссылка на которую укладывается среди полей объекта (таблица методов интерфейса). В ней хранятся указатели на методы класса, реализующие методы интерфейса. Интерфейсная переменная хранит ссылку на скрытое поле объекта, которое содержит указатель на таблицу методов интерфейса. Когда интерфейсной переменной присваивается значение объектой переменной,
Intf:= Obj; // где Intf: ITextReader иObj: TTextReader
К адресу объекта добавляется смещение до скрытого поля внутри объекта и этот результат заносится в интерфейсную переменную.
|
||||
Последнее изменение этой страницы: 2016-08-14; просмотров: 453; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.144.2.5 (0.008 с.) |