Событие (объектно-ориентированное программирование)

Событие в объектно-ориентированном программировании — это сообщение, которое возникает в различных точках исполняемого кода при выполнении определённых условий.

События предназначены для того, чтобы иметь возможность предусмотреть реакцию программного обеспечения.[1]

Для решения поставленной задачи создаются обработчики событий: как только программа попадает в заданное состояние, происходит событие, посылается сообщение, а обработчик перехватывает это сообщение. В общем случае в обработчик не передаётся ничего, либо передаётся ссылка на объект, инициировавший (породивший) обрабатываемое событие. В особых случаях в обработчик передаются значения некоторых переменных или ссылки на какие-то другие объекты, чтобы обработка данного события могла учесть контекст возникновения события.

Самое простое событие — это событие, сообщающее о начале или о завершении некоторой процедуры. Событие, по сути, сообщает об изменении состояния некоторого объекта. Наиболее наглядно события представлены в пользовательском интерфейсе, когда каждое действие пользователя порождает цепочку событий, которые, затем обрабатываются в приложении.

Общее описание править

В объектно-ориентированном анализе для описания динамического поведения объектов принято использовать модель состояний.[2]

Событие — это переход объекта из одного состояния в другое. Взаимодействие объектов также осуществляется при помощи событий: изменение состояния одного объекта приводит к изменению состояния другого объекта, а событие оказывается средством связи между объектами.

Согласно[2], событие — это «абстракция инцидента или сигнала в реальном мире, который сообщает нам о перемещении чего-либо в новое состояние». Далее, выделяются четыре аспекта события:

  • метка — уникальный идентификатор события.
  • значение — текстовое сообщение о сути произошедшего.
  • предназначение — модель событий, которая принимает событие.
  • данные — данные, которые переносятся от одного объекта к другому.

Примеры править

Первый ряд примеров событий доставляет собственно сам жизненный цикл объекта:

  • создание объекта;
  • уничтожение объекта.

Более сложные примеры событий возникают тогда, когда у объекта появляются внутренние состояния, которые описываются соответствующей диаграммой переходов (из одного состояния в другое).

События в .Net править

 
Делегатно-событийная модель. clickme — источник события — кнопка содержит список наблюдателей (слушателей).

События позволяют классу или объекту уведомлять другие классы или объекты о возникновении каких-либо ситуаций. Класс, отправляющий (или вызывающий) событие, называется издателем, а классы, принимающие (или обрабатывающие) событие, называются подписчиками. События представляют собой экземпляры делегатов, способные хранить, добавлять и удалять делегаты такого же типа (обработчики событий). При вызове события вызываются все делегаты, которые были добавлены к событию. События могут быть вызваны только из класса или объекта, которому принадлежит событие.[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

См. также править

Ссылки править

Примечания править

  1. В этом смысле события похожи на прерывания.
  2. 1 2 См. [1].
  3. 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. Архивировано 20 сентября 2011 года.

Литература править

  1. Шлеер С, Меллор С. Объектно-ориентированный анализ: моделирование мира в состояниях: Пер. с англ. — Киев : Диалектика, 1993. — 240 с: ил.