Основные сведения об интерфейсах
Объектно-ориентированное программирование – мощная методология, помогающая в проектировании и реализации больших программных систем. Использование классов позволяет применять обобщение (абстракцию) и инкапсуляцию. С помощью классов большая система может быть естественным образом разбита на удобные в обращении части. Наследование является еще одним удобным средством структурирования системы, которое позволяет поместить общие черты разных частей в один базовый класс, благодаря чему достигается возможность повторного использования программного кода.
Основной задачей интерфейсов является определить контракт, не зависящий от реализации. Каждый интерфейс имеет набор методов, не реализованных непосредственно. Для каждого метода определена сигнатура, описывающая количество и тип аргументов, а также тип возвращаемого методом значения.
Интерфейсы в управляемом C++
В Visual C++ .NET для определения интерфейсов используется ключевое слово _interface (интерфейс). Само же определение подобно определению класса. Так же, как и классы, интерфейсы являются ссылочными типами, а для определения их как управляемых используется ключевое слово _gс (сборщик мусора). Наибольшее отличие интерфейсов от классов (как управляемых, так и неуправляемых) – отсутствие конкретной реализации для интерфейсов; они представляют собой чистые спецификации. Тем не менее, подобно классам, интерфейсы могут иметь свойства (property), индексаторы (indexer) и, конечно же, методы.
На примере интерфейса ICustomer продемонстрируем определение методов, используемых клиентами системы Бюро путешествий Acme (Acme Travel Agency).
_gc _interface Icustomer // сборщик мусора – ICustomer { public: int RegisterCustomer; String *pFirstName, String *pLastName, String *pEmailAddress); void UnregisterCustomer(int id); // идентификатор ArrayList *GetCustomer(int id); // идентификатор void ChangeEmailAddress(int id, String *pEmailAddress); // (int идентификатор, Строка *pEmailAddress); };
Описания методов RegisterCustomer, UnregisterCustomer и ChangeEmailAddress полностью совпадают с сигнатурами одноименных методов, реализованных нами в классе Customer (Клиент). Метод GetCustomer является новым. Ранее мы использовали метод ShowCustomer, выводящий на экран список клиентов. Этот метод использовался временно. Однако лучше возвращать по запросу сами данные и предоставить пользователю самому решать, что с ними делать.
Метод GetCustomer возвращает информацию об одном или нескольких клиентах в списке массивов. Когда в качестве идентификатора клиента задается значение -1, возвращается информация обо всех зарегистрированных клиентах. В противном случае возвращаемый список содержит информацию о клиенте с заданным идентификатором. Если среди клиентов нет клиента с таким идентификатором, возвращаемый список будет пустым.
Наследование для интерфейсов
Интерфейс может быть потомком другого интерфейса (однако управляемый интерфейс не может быть потомком неуправляемого, и наоборот). В отличие от классов, для которых допустимо лишь единичное наследование, допускается множественное наследование интерфейсов, т.е. интерфейс может иметь несколько непосредственных родителей. Например, интерфейс ICustomer может быть определен как производный от двух более мелких интерфейсов IBasicCustomer и ICustomerlnfo. Заметим, что в описании указанных трех интерфейсов не задается спецификатор открытого доступа. Это потому, что интерфейсы общедоступны по умолчанию.
_gc _interface IBasicCustomer // сборщик мусора – IBasicCustomer { int RegisterCustomer( String *pFirstName, String *pLastName, String *pEmailAddress); void UnregisterCustomer(int id); // идентификатор void ChangeEmailAddress(int id, String *pEmailAddress); // (int идентификатор, Строка *pEmailAddress); }; _gc _interface ICustomerlnfo // сборщик мусора – ICustomerlnfo { ArrayList *GetCustomer(int id); // идентификатор }; _gc _interface ICustomer: IBasicCustomer, ICustomerlnfo // сборщик мусора – ICustomer: IBasicCustomer, ICustomerlnfo { };
При таком объявлении интерфейса можно также определить новые методы, как это сделано ниже для интерфейса ICustomer2.
_gc _interface ICustomer2: IBasicCustomer, ICustomerlnfo // сборщик мусора – ICustomer2: IBasicCustomer, ICustomerlnfo { void NewMethod(); };