|
||||||||
|
Использование интерфейсовВ документации Delphi описывается семантика использования интерфейсов, поэтому iприводить ее здесь не имеет смысла. Вместо этого рассмотрим, как интерфейс IUnknown ?бесшовно? интегрируется в Object Pascal. Когда переменной интерфейса присваивается значение, компилятор автоматически генерирует вызов метода _AddRef(), и таким образом счетчик ссылок увеличивается. Когда переменная интерфейса выходит за пределы видимости или принимает значение nil компилятор автоматически генерирует вызов метода _Release(). Рассмотрим следующий фрагмент кода: var А сейчас обратите внимание на следующий код, который вводит разработчик (выделен полужирным шрифтом), и код, который неявно генерируется компилятором (обычный шрифт) при реализации приведенного ранее фрагмента: var Компилятор Delphi также достаточно сообразителен и знает, когда вызванные методы _AddRef() и _Release() переназначаются экземпляру другого интерфейса или принимают значение nil. Рассмотрим такой код: var Вновь совместим написанную нами часть кода (полужирный шрифт) с неявно сгенерированным компилятором (обычный). В результате получится следующее: var Приведенный пример помогает понять, почему Delphi использует символ подчеркивания в методах _AddRef() и _Release(). Об увеличении или уменьшении числа ссылок интерфейса часто забывали, и это было классической ошибкой при программировании СОМ в те времена, когда не было ключевого слова interface. Интерфейсы Delphi помогают разработчику, устраняя эти проблемы с помощью неявного вызова этих методов. Поскольку компилятор знает, как генерировать вызовы _AddRef() и _Release(), может, ему присуще и свойство компилировать третий метод, Querylnterface(), интерфейса IUnknown? Да, он умеет делать и это. Взяв указатель интерфейса для объекта, можно использовать оператор as для подбора интерфейса, поддерживаемого СОМ-объектом. Понятие "подбор" наилучшим образом подходит для описания этого процесса, поскольку такое применение оператора as является нереальным подбором в точном смысле, но внутри него вызывается метод Querylnterface(). Вот демонстрация сказанного выше: var В этом примере исключительная ситуация порождается оператором as, если объект ссылается на I1, который не поддерживается интерфейсом ISomeOtherInterface. Одно дополнительное правило языка относительно интерфейсов заключается в следующем: переменные интерфейса совместимы по присвоению с классом Object Pascal, который реализует этот интерфейс. Например, рассмотрим следующее объявление интерфейса и класса:; type Используя предыдущие объявления, скорректируем код следующим образом: var Несмотря на то, что эта особенность, как кажется, нарушает традиционные правила Pascal о совместимости по присвоению, это делает интерфейсы более естественными и простыми в работе. Существует важный, но не очевидный вывод из этих правил ? интерфейсы совместимы по присвоению только с классами, которые явно поддерживают этот интерфейс. Например, класс TBarClass, определенный выше, объявляет явную поддержку интерфейса IBar. Поскольку интерфейс IBar наследуется от интерфейса IFoo, резонно предположить, что интерфейс TBarClass также поддерживает IFoo. Однако это вовсе не так, как иллюстрируется в приведенном ниже фрагменте: var
| |||||||||
За содержание страницы отвечает Гончарова М.Н. © Кафедра СПиКБ, 2002-2017 |