Обработка событий с точки зрения ООП
Предыдущие версии Visual Basic убедительно показали, что модель программирования, управляемая событиями и основанная на применении объектов, повышает производительность труда программиста. Стоило вам перетащить элемент на форму, как он начинал реагировать на определенные события. Например, код процедуры события Button1_Click автоматически выполнялся при нажатии кнопки с именем Button1.
Но, несмотря на эффективность, модель, использованная в прежних версиях VB, была недостаточно гибкой. В частности, в ней было трудно определять новые события, а написать обработчик, который обрабатывает сразу несколько событий, было практически невозможно. В VB.NET удобство и эффективность объединились с богатством возможностей. Обычно используется синтаксис, очень близкий к синтаксису прежних версий VB, при этом VB.NET берет на себя всю "черную работу". Если понадобится сделать что-то нестандартное – VB.NET предоставит и такую возможность.
Глава начинается с описания модели обработки событий, похожей на аналогичную модель из предыдущих версий VB (хотя и гораздо более мощной). Далее мы представим новую для VB концепцию делегатов и покажем, как с их помощью в полной мере использовать возможности платформы .NET по обработке событий, а также решать более общие задачи (например, организовать обратный вызов функций).
Поскольку сущность объектно-ориентированного программирования в конечном счете сводится к обмену сообщениями между взаимодействующими объектами, события должны занимать определенное место в этой схеме. В каком-то отношении они нормально вписываются в нее: объект-источник отправляет сообщение, которое указывает на возникновение события.
Но при этом возникает очевидная проблема: каким объектам следует отправлять сообщения? Оповещать о каждом событии все объекты, в настоящий момент существующие в программе? Это было бы слишком неэффективно. Для большинства объектов событие не представляет ни малейшего интереса, а быстродействие станет неприемлемо низким.
Вместо этого VB.NET пытается ограничить число получателей события, для чего используется модель "подписка/публикация". В этой модели объекты-приемники событий регистрируют объекты-источники тех событий, которые представляют для них интерес. На события от одного источника могут подписаться сразу несколько объектов-приемников. О том, что источник инициировал событие, оповещаются только зарегистрированные получатели.
Впрочем, реализовать подобную схему не так просто. Какие сообщения должны передаваться приемнику от источника? Как организовать их отправку? Что должно происходить при получении сообщения? Как говорилось выше, взаимодействие между объектами на базе обмена сообщениями строится на вызове методов класса-приемника. В конечном счете обработка событий строится по тому же принципу, но при этом приходится учитывать ряд дополнительных тонкостей.
Общий смысл происходящего заключается в том, что при возникновении события объект-источник вызывает заранее определенные функции объектов-приемников. Вызываемая функция приемника регистрируется источником события одновременно с регистрацией объекта-приемника. Такая схема называется оповещением посредством обратного вызова (callback notification), потому что источник события вызывает метод приемника по заранее известному ему адресу. На рис. 6.1 показан объект-"начальник" с событием HighRating, при возникновении вызываются разные методы объектов-приемников. Во второй половине этой главы будет рассказано, как это происходит в VB.NET.
Примечание
Чтобы регистрация прошла успешно, методы объекта-приемника должны иметь строго определенную форму (например, обладать конкретной сигнатурой). По этой причине в некоторых языках (например, в Java) механизм обратного вызова реализуется с применением интерфейсов – это гарантирует наличие метода с правильной сигнатурой.
Рис. 6.1. Схема оповещения посредством обратного вызова