Событие (объектно-ориентированное программирование)
Событие в объектно-ориентированном программировании — это сообщение, которое возникает в различных точках исполняемого кода при выполнении определённых условий.
События предназначены для того, чтобы иметь возможность предусмотреть реакцию программного обеспечения.[1]
Для решения поставленной задачи создаются обработчики событий: как только программа попадает в заданное состояние, происходит событие, посылается сообщение, а обработчик перехватывает это сообщение. В общем случае в обработчик не передаётся ничего, либо передаётся ссылка на объект, инициировавший (породивший) обрабатываемое событие. В особых случаях в обработчик передаются значения некоторых переменных или ссылки на какие-то другие объекты, чтобы обработка данного события могла учесть контекст возникновения события.
Самое простое событие — это событие, сообщающее о начале или о завершении некоторой процедуры. Событие, по сути, сообщает об изменении состояния некоторого объекта. Наиболее наглядно события представлены в пользовательском интерфейсе, когда каждое действие пользователя порождает цепочку событий, которые, затем обрабатываются в приложении.
Общее описание
В объектно-ориентированном анализе для описания динамического поведения объектов принято использовать модель состояний.[2]
Событие — это переход объекта из одного состояния в другое. Взаимодействие объектов также осуществляется при помощи событий: изменение состояния одного объекта приводит к изменению состояния другого объекта, а событие оказывается средством связи между объектами.
Согласно[2], событие — это «абстракция инцидента или сигнала в реальном мире, который сообщает нам о перемещении чего-либо в новое состояние». Далее, выделяются четыре аспекта события:
- метка — уникальный идентификатор события.
- значение — текстовое сообщение о сути произошедшего.
- предназначение — модель событий, которая принимает событие.
- данные — данные, которые переносятся от одного объекта к другому.
Примеры
Первый ряд примеров событий доставляет собственно сам жизненный цикл объекта:
- создание объекта;
- уничтожение объекта.
Более сложные примеры событий возникают тогда, когда у объекта появляются внутренние состояния, которые описываются соответствующей диаграммой переходов (из одного состояния в другое).
События в .Net
События позволяют классу или объекту уведомлять другие классы или объекты о возникновении каких-либо ситуаций. Класс, отправляющий (или вызывающий) событие, называется издателем, а классы, принимающие (или обрабатывающие) событие, называются подписчиками. События представляют собой экземпляры делегатов, способные хранить, добавлять и удалять делегаты такого же типа (обработчики событий). При вызове события вызываются все делегаты, которые были добавлены к событию. События могут быть вызваны только из класса или объекта, которому принадлежит событие.[3] Делегатно-событийная модель, применяемая, например, при разработке графических интерфейсов, основана на:
- управляющем объекте, который является источником событий
- наблюдателе, который также называется обработчиком событий, который получает уведомления о событиях от источника
- интерфейсах (в более широком смысле), которые описывают способ (протокол) обмена событиями.
К тому же, модель требует, чтобы:
- каждый наблюдатель реализовал интерфейс для событий, на которые он хочет подписаться
- каждый наблюдатель должен зарегистрироваться в источнике, чтобы выразить о намерении получать события.
- каждый раз, когда источник генерирует событие, он передаёт его наблюдателям по протоколу интерфейса.
В C#
delegate void Notifier (string sender);
class Model {
public event Notifier notifyViews;
public void Change() { ... notifyViews("Model"); }
}
class View1 {
public View1(Model m) {
m.notifyViews += new Notifier(this.Update1);
}
void Update1(string sender) {
Console.WriteLine(sender + " was changed during update");
}
}
class View2 {
public View2(Model m) {
m.notifyViews += new Notifier(this.Update2);
}
void Update2(string sender) {
Console.WriteLine(sender + " was changed");
}
}
class Test {
static void Main() {
Model model = new Model();
new View1(model);
new View2(model);
model.Change(); // Оба метода Update1 и Update2 вызовутся.
}
}
В VB.NET
В VB.NET события объявляются ключевым словом Event. Если опущен тип делегата, то компилятор сам создаст его, который может в дальнейшем содержать ссылку на метод, реализованный в подписчике.
Реализовать подписку на событие можно несколькими способами:
- evtSample As sampleDel — механизм регистрации обработчика события для данного типа декларации должен быть предоставлен классом с объявленным событием. Событие генерируется путём вызова метода в делегате evtSample.
- Public Event evtSample As sampleDel — обработчик событий может быть зарегистрирован с помощью оператора AddHandler, который свяжет событие источника и метод в классе подписчика. Событие реализуется с помощью объявленного делегата sampleDel. Событие генерируется используя оператор RaiseEvent.
- Public Event evtSample — обработчик события будет зарегистрирован с помощью ключевых слов WithEvents в объявлении экземпляра класса и Handles в самой декларации метода класса подписчика. Событие реализуется с помощью неявно объявленного делегата. Событие генерируется используя оператор RaiseEvent.
Imports System
Public Class CTimer
Delegate Sub SecondDel(ByVal xintTime As Integer)
Private evtSecond As SecondDel
Public Event evtMinute As SecondDel
Public Event evtHour(ByVal xHour As Integer)
public Shared lngSeconds As Long
Public Sub Register(ByVal objSecond As SecondDel)
evtSecond = evtSecond.Combine(evtSecond, objSecond)
End Sub
Public Sub OnTimer()
lngSeconds = lngSeconds + 1
If lngSeconds Mod 5 = 0 Then
evtSecond(lngSeconds) 'Вызов метода делегата
End If
If lngSeconds Mod 10 = 0 Then
RaiseEvent evtMinute(lngSeconds) 'Генерация события
End If
If lngSeconds Mod 30 = 0 Then
RaiseEvent evtHour(lngSeconds) 'Генерация события
End If
End Sub
End Class
Public Class CClock
Private WithEvents mobjTimer As CTimer 'Объявление объекта класса, с возможностью подключения к событиям
Sub New()
mobjTimer = New CTimer()
mobjTimer.Register(New CTimer.SecondDel(AddressOf SecondEvent)) 'Регистрация события через метод предоставленный классом
AddHandler mobjTimer.evtMinute, AddressOf MinuteEvent 'Регистрация события с помощью оператора AddHandler
While (mobjTimer.lngSeconds < 60)
mobjTimer.OnTimer()
System.Threading.Thread.Sleep(100)
End While
End Sub
Private Sub SecondEvent(ByVal xintTime As Integer)
Console.WriteLine("Second's Event")
End Sub
Private Sub MinuteEvent(ByVal xintTime As Integer)
Console.WriteLine("Minute's Event")
End Sub
'Регистрация события с помощью ключевого слова Handles
Private Sub mobjTimer_evtHour(ByVal xintTime As Integer) Handles mobjTimer.evtHour
Console.WriteLine("Hour's Event")
End Sub
Public Shared Sub Main()
Dim cc1 = New CClock()
End Sub
End Class
См. также
Ссылки
- Визуальное объектно-ориентированное программирование
- Введение в объектно-ориентированное программирование (недоступная ссылка)
- Основы объектно-ориентированного визуального программирования
- Article Event Handling in VB.NET
- Events and Event Handlers in VB.NET
- event keyword in C#
- Events and Delegates .NET Framework
Примечания
- В этом смысле события похожи на прерывания.
- См. [1].
- Mössenböck, Hanspeter Advanced C#: Variable Number of Parameters 26. http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/:+ Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik (25 марта 2002). Дата обращения: 5 августа 2011.
Литература
- Шлеер С, Меллор С. Объектно-ориентированный анализ: моделирование мира в состояниях: Пер. с англ. — Киев : Диалектика, 1993. — 240 с: ил.