Створення і використання інтерфейсу - delphi sources faq

Інтерфейси грають головну роль в технологіях СОМ (Component Object Model - компонентна модель об'єктів), CORBA (Common Object Request Broker Architecture - архітектура з брокером необхідних загальних об'єктів) та пов'язаних з ними технологіях віддаленого доступу, т. Е. Технологіях доступу до об'єктів, розташованих (і що виконується) на іншій машині. Їх основне завдання - описати властивості, методи і події віддаленого об'єкта в термінах машини клієнта, т. Е. На використовуваному при розробці клієнтської програми мовою програмування. За допомогою інтерфейсів програма клієнта звертається до віддаленого об'єкту так, як якщо б він був її власним об'єктом.

Тема інтерфейсів досить обширна і цікава. У цьому розділі даються лише найзагальніші відомості про інтерфейси. Зведення цієї теми в одну главу з класами не випадково, т. К. Інтерфейс являє собою порожній клас, т. Е. Клас, в якому проголошені, але ніяк не розшифровані властивості і методи.

Інтерфейси є окреме питання опису типів. Вони оголошуються за допомогою зарезервованого слова interface. наприклад:

На відміну від класів інтерфейс не може містити поля, і, отже, які оголошуються в ньому властивості в розділах read і write можуть посилатися тільки на методи. Все оголошуються в інтерфейсі члени розміщуються в єдиній секції public. Методи не можуть бути абстрактними (abstract), віртуальними (virtual), динамічними (dynamic) або перекриваються (override). Інтерфейси не можуть мати конструкторів або деструкторів, т. К. Описувані в них методи реалізуються тільки в рамках підтримують їх класів, які називаються інтерфейсними.

На відміну від звичайного класу інтерфейсний клас може мати більше одного батьківського інтерфейсу:

У будь-якому випадку в розділі реалізації интерфейсного класу необхідно описати відповідні інтерфейсні методи. Якщо, наприклад, оголошений інтерфейс

і використовує його інтерфейсний клас

то в розділі implementation слід вказати реалізацію методів:

Тепер можна оголосити інтерфейсний, об'єкт класу TPainter, щоб з його допомогою намалювати коло і квадрат:

було б помилкою: компілятор зажадав би вставити опис методів CirclePaint і RectPaint.

Подібно до того як всі класи в Object Pascal породжені від єдиного батька TObject, все інтерфейсні класи породжені від загального предка TInterfacedObject. Цей предок вміє розподіляти пам'ять для інтерфейсних об'єктів і використовує глобальний інтерфейс lunknow:

Якби в попередньому прикладі клас TPainter був описаний так:

компілятор зажадав би описати відсутні методи Queryinterface, _Add І _Release класу TInterfacedObject. Поле FRef Count цього класу служить лічильником викликів интерфейсного об'єкта і використовується за прийнятою в Windows схемою: при кожному зверненні до методу Add інтерфейсу IUnknow лічильник нарощується на одиницю, при кожному зверненні до Release - на одиницю скидається. Коли значення цього поля стає дорівнює 0, інтерфейсний об'єкт знищується і звільняється займана ним пам'ять.

Якщо інтерфейс передбачається використовувати в технологіях COM / DCOM або CORBA, його методи повинні описувати з директивою stdcall або (для об'єктів Автоматизації) safecall

До интерфейсному об'єкту можна застосувати оператор приведення типів as, щоб використовувати потрібний інтерфейс:

Зустрівши таке присвоєння, компілятор створить код, за допомогою якого викликається метод Queryinterface інтерфейсу IUnknow з вимогою повернути посилання на інтерфейс IPaint. Якщо об'єкт не підтримує вказаний інтерфейс, виникає виняткова ситуація.

Інтерфейси, розраховані на використання в віддалених об'єктах, повинні забезпечуватися глобально-унікальний ідентифікатор (guiD). наприклад:

Глобально-унікальні ідентифікатори створюються за спеціальною технологією, яка гарантує мізерну ймовірність того, що два guid співпадуть. Ця технологія включена в Windows 32: щоб отримати guid для новоствореного інтерфейсу в середовищі Delphi, досить натиснути клавіші Ctrl + Shift + G. Для роботи з guid в модулі System оголошені наступні типи:

Програміст може оголошувати типізовані константи типу tguid, наприклад:

Константи guid можуть використовуватися замість імен інтерфейсів при виклику підпрограм. Наприклад, два наступних звернення ідентичні:

За допомогою зарезервованого слова implements програміст може делегувати будь-якого властивості деякого класу повноваження інтерфейсу. Це властивість має мати тип інтерфейсу або класу. Якщо властивість має тип інтерфейсу, ім'я цього інтерфейсу має зазначатися в списку батьків класу, як якщо б це був інтерфейсний клас:

Зверніть увагу: в цьому прикладі клас TMyciass не є інтерфейсним, т. Е. Класом, в якому виконуються методи p1 і P2. Однак якщо з нього прибрати визначення уповноваженого властивості Mylnterface, він стане інтерфейсним, і в ньому повинні бути описані методи інтерфейсу IMylnterface.

Уповноважена властивість обов'язково повинно мати частину read. Якщо воно має тип класу, клас, в якому воно оголошено, не може мати інших уповноважених властивостей.