Delphi. Интерфейсы в простых примерах

Решил разобраться для себя с тем, что такое интерфейсы, хотя бы в первом приближении. Много где они используются в современном Delphi – и FireMonkey и в COM и др. В данной статье – все самое простое – что такое интерфейс и как им пользоваться в самом простом случае.

Что такое интерфейс?

Интерфейс, это сущность, содержащая в себе уникальный номер (GUID) и список методов, но не содержащая в себе их реализацию. Для реализации создается отдельный класс, в родителях которого прописывается данный интерфейс. Интерфейс, также, не содержит свойств.

Итак, в секции type объявим интерфейс

Номер  [‘{CAD11BF9-BEFD-4838-A56E-BB6BF40EE513}’] генерируется автоматически после нажатия на Ctrl+Shift+G. Он уникален и по расчету разработчиков алгоритма – никогда не повторится, ни на одном компьютере мира.

Объявим также в секции type класс, для реализации методов интерфейса

Реализуем методы класса, нажав на Ctrl+Shift+C

И последний штрих – вызовем метод SayHello по клику на кнопку

Обратите внимание ! Мы  не удаляли экземпляр класса!!! Это особенность работы с интерфейсами. При создании экземпляра класса и присвоении его интерфейсной переменной MyInterface – так называемый счетчик ссылок увеличивается на единицу.

То есть, вот эта строка

 

увеличила счетчик ссылок на единицу. Но об этом подробнее чуть позже. При определенных условиях счетчик уменьшается на единицу либо обнуляется.. При обнулении – экземпляр класса уничтожается.

Посмотрим как это работает

1

При закрытии сообщения увидим вот это

2

Экземпляр класса удаляется у нас сам, после того, как отработал метод.

Как завладеть временем жизни экземпляра класса интерфейса?

Если не нужно, чтобы экземпляр класса создавался и удалялся по 100 раз при вызове методов, можно управлять временем его жизни. Создать его 1 раз и удалить тогда когда нужно.

Нужно сделать 2 изменения в предыдущем коде – при объявлении класса, поддерживающего интерфейс

Первое изменение

Второе изменение

В данном случае удаление экземпляра произойдет вместе, с удалением владельца. Попробуем закрыть форму.

3


Как работают счетчики ссылок?

Выше мы объявляли свой интерфейс и поддерживающий его класс вот так…

Если немного покопаться, то IUnknown находится в модуле System и имеет 3 метода

_AddRef – добавляет счетчик ссылок

_Release уменьшает счетчик ссылок

Querylnterface возвращает указатель на интерфейс объекта по его идентификатору

Немного поэкспериментируем

Если объявить 2 метода SayHello и SayHello2 и вызвать их подряд, то получим следующее

2

Если вызвать методы в разных кнопках, то экземпляр не удаляется даже после вызова 2 метода, а ждет пока не отработает программа

4

Ну и так далее. Думаю это поле для экспериментов в реальных задачах.

Как уничтожить экземпляр класса, создаваемый для интерфейса?

Ранее, мы объявляли интерфейсную переменную

Чтобы уничтожить экземпляры класса, рожденные для этой переменной, достаточно занулить ссылку