Определение и реализация интерфейсов в Delphi

В Delphi«Интерфейс» имеет два разных значения. В OOP Жаргон, вы можете думать об интерфейсе как о классе без реализации. В разделе определения раздела Delphi интерфейс используется для объявления любых открытых разделов кода, которые появляются в модуле. В этой статье будут описаны интерфейсы с точки зрения ООП.

Если вы хотите создать надежное приложение таким образом, чтобы ваш код можно было обслуживать, использовать повторно и гибко, OOP Природа Дельфи поможет вам проехать первые 70% вашего маршрута. Определение интерфейсов и их реализация помогут с оставшимися 30%.

Абстрактные классы

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

Давайте посмотрим на пример описания интерфейса:

тип
IConfigChanged = интерфейс[ '{0D57624C-CDDE-458B-A36C-436AE465B477}']
процедура ApplyConfigChange;
конец;
instagram viewer

IConfigChanged это интерфейс. Интерфейс определен во многом как класс, ключевое слово «интерфейс» используется вместо «класс». Значение Guid, следующее за ключевым словом интерфейса, используется компилятором для однозначной идентификации интерфейса. Чтобы создать новое значение GUID, просто нажмите Ctrl + Shift + G в Delphi IDE. Каждый определяемый вами интерфейс требует уникального значения Guid.

Интерфейс в ООП определяет абстракцию - шаблон для фактического класса, который будет реализовывать интерфейс - который будет реализовывать методы, определенные интерфейсом. Интерфейс на самом деле ничего не делает, он имеет только сигнатуру для взаимодействия с другими (реализующими) классами или интерфейсами.

Реализация методов (функций, процедур и свойств Get / Set) выполняется в классе, который реализует интерфейс. В определении интерфейса нет разделов области действия (приватных, общедоступных, опубликованных и т. Д.), Все общедоступно. Тип интерфейса может определять функции, процедуры (которые в конечном итоге станут методами класса, реализующего интерфейс) и свойства. Когда интерфейс определяет свойство, он должен определять методы get / set - интерфейсы не могут определять переменные.

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

тип
IConfigChangedMore = интерфейс(IConfigChanged)
процедура ApplyMoreChanges;
конец;

программирование

Большинство разработчиков Delphi, когда думают об интерфейсах, думают о программировании COM. Тем не менее, интерфейсы - это просто ООП-функция языка - они не привязаны специально к COM. Интерфейсы могут быть определены и реализованы в приложении Delphi, не затрагивая COM вообще.

Реализация

Для реализации интерфейса вам нужно добавить имя интерфейса в оператор класса, как в:

тип
TMainForm = учебный класс(TForm, IConfigChanged)
общественности
процедура ApplyConfigChange;
конец;

В приведенном выше коде форма Delphi с именем «MainForm» реализует интерфейс IConfigChanged.

Предупреждение: когда класс реализует интерфейс, он должен реализовать все свои методы и свойства. Если вы потерпите неудачу / забудете реализовать метод (например: ApplyConfigChange), ошибка времени компиляции "E2003 Необъявленный идентификатор: 'ApplyConfigChange'" произойдет.
ПредупреждениеЕсли вы попытаетесь указать интерфейс без значения GUID, вы получите: «E2086 Тип« IConfigChanged »еще не определен полностью».

пример

Рассмотрим приложение MDI, в котором пользователю могут отображаться несколько форм одновременно. Когда пользователь изменяет конфигурацию приложения, большинству форм необходимо обновить их отображение - показать / скрыть некоторые кнопки, обновить подписи к меткам и т. Д. Вам понадобится простой способ уведомить все открытые формы о том, что произошло изменение в конфигурации приложения. Идеальным инструментом для работы был интерфейс.

Каждая форма, которую необходимо обновить при изменении конфигурации, будет реализовывать IConfigChanged. Поскольку экран конфигурации отображается модально, когда он закрывается, следующий код обеспечивает уведомление всех реализующих форм IConfigChanged и вызывается ApplyConfigChange:

процедура DoConfigChange ();
вар
cnt: целое число;
icc: IConfigChanged;
начать
за cnt: = 0 в -1 + Экран. FormCount делать
начать
если Поддерживает (Экран. Forms [cnt], IConfigChanged, icc) тогда
МЦЙ. ApplyConfigChange;
конец;
конец;

Поддерживает функция (определяется в Sysutils.pas) указывает, поддерживает ли данный объект или интерфейс указанный интерфейс. Код перебирает экран. Коллекция форм (объекта TScreen) - все формы, отображаемые в данный момент в приложении. Если форма Экран. Формы [CNT] поддерживает интерфейс, Supports возвращает интерфейс для параметра последнего параметра и возвращает true.

Следовательно, если форма реализует IConfigChanged, переменную icc можно использовать для вызова методов интерфейса, реализованных в форме. Обратите внимание, конечно, что каждая форма может иметь своя собственная реализация процедуры ApplyConfigChange.

Предки

Любой класс, который вы определяете в Delphi, должен иметь предка. TObject является предком всех объектов и компонентов. Вышеприведенная идея применима и к интерфейсам, IInterface является базовым классом для всех интерфейсов. IInterface определяет 3 метода: QueryInterface, _AddRef и _Release.

Это означает, что наш IConfigChanged также имеет эти 3 метода, но мы их не реализовали. Это потому, что TForm наследует от TComponent, который уже реализует IInterface для вас! Если вы хотите реализовать интерфейс в классе, который наследуется от TObject, убедитесь, что ваш класс наследует от TInterfacedObject. Так как TInterfacedObject является TObject, реализующим IInterface. Например:

TMyClass = учебный класс(TInterfacedObject, IConfigChanged)
процедура ApplyConfigChange;
конец;

В заключение, IUnknown = IInterface. IUnknown для COM.

instagram story viewer