В языке Delphi интерфейсы описываются в секции type глобального блока. Описание начинается с ключевого слова interface и заканчивается ключевым словом end. По форме объявления интерфейсы похожи на обычные классы, но в отличие от классов:
- интерфейсы не могут содержать поля;
- интерфейсы не могут содержать конструкторы и деструкторы;
- все атрибуты интерфейсов являются общедоступными (public);
- все методы интерфейсов являются абстрактными (virtual, abstract).
Приведем пример интерфейса и сразу заметим, что интерфейсам принято давать имена, начинающиеся с буквы I (от англ. Interface):
type ITextReader = interface // Методы function NextLine: Boolean; // Свойства property Active: Boolean; property ItemCount: Integer; property Items[Index: Integer]: string; property EndOfFile: Boolean; end; |
Интерфейс ITextReader предназначен для считывания табличных данных из текстовых источников. В главе 3 мы уже создавали объекты, которые умеют это делать, поэтому назначение методов и свойств должно быть вам понятно. Непонятно пока другое — зачем вообще нужен интерфейс для доступа к табличным данным, если уже есть готовый класс TTextReader с требуемой функциональностью.
Объяснение состоит в следующем. Не определив интерфейс ITextReader, невозможно разместить класс TTextReader в DLL-библиотеке и обеспечить доступ к нему из EXE-программы. Создавая DLL-библиотеку, мы с помощью оператора uses должны включить модуль ReadersUnit в проект библиотеки. Создавая EXE-программу, мы должны включить модуль ReadersUnit и в нее, чтобы воспользоваться описанием класса TTextReader. Но тогда весь программный код класса попадет внутрь EXE-файла, а это именно то, от чего мы хотим избавиться. Решение проблемы обеспечивается введением понятия интерфейса.
Чтобы вам было легче разобраться с интерфейсом ITextReader, мы привели его незаконченный вариант. Компиляция интерфейса в таком виде приведет к ошибкам: для свойств не указаны методы чтения и записи. Полное описание интерфейса выглядит так:
type ITextReader = interface // Методы function NextLine: Boolean; procedure SetActive(const Active: Boolean); function GetActive: Boolean; function GetItemCount: Integer; function GetItem(Index: Integer): string; function GetEndOfFile: Boolean; // Свойства property Active: Boolean read GetActive write SetActive; property Items[Index: Integer]: string read GetItem; default; property ItemCount: Integer read GetItemCount; property EndOfFile: Boolean read GetEndOfFile; end; |
Поскольку интерфейс не может содержать поля, все его свойства отображены на его методы.