ПОНЯТНО О Visual Basic NET (том 3)

Первый способ создания и обработки событий: WithEvents


Задача. Давайте смоделируем такую ситуацию: На вашем счете в банке лежит какая-то сумма. Вы приходите в магазин и хотите расплатиться за покупку кредитной карточкой, открытой на этот счет в банке. Вы отдаете карточку кассиру, тот направляет в банк приказ снять с вашего счета нужную сумму, приказ выполняется, кассир вам карточку возвращает. Все, покупка сделана. Задача программиста состоит в том, чтобы предусмотреть запрет на выполнение этой операции, если вы накупили товаров на сумму, превышающую ту, что у вас на счете. При этом у кассира должно возникнуть сообщение «На счете не хватает денег».

Приступим к решению. Магазин и банк относятся к тем фирмам, которые предпочитают хранить свою финансовую информацию в секрете друг от друга. Поэтому пусть магазин будет у нас формой, а для банка создадим свой класс. Класс будет очень простой, он ограничится вашим счетом и его обработкой.

Создайте проект. Разместите на форме текстовое поле, кнопку и метку. Создайте в проекте класс clsСчет. В этом классе будет присутствовать переменная Сумма_на_счете, объявленная Private, чтобы в магазине случайно не раскрыли тайну вклада клиента. Кроме этого в классе будет присутствовать метод Снятие_со_счета, смысл которого ясен из названия. Кассир вводит в текстовое поле сумму покупок, затем нажатием на кнопку формы запускает упомянутый метод, метод проверяет, хватает ли денег на счете, и если да, то уменьшает эти деньги на сумму покупок, а если нет, то порождает некое событие («передает сигнал» – RaiseEvent). На форме уже ждет наготове обработчик этого события. Он его воспринимает («принимает сигнал») и начинает выполняться, в результате чего метка на форме покажет текст «На счете не хватает денег».

С учетом сказанного разберитесь в приведенном ниже коде, а новинки я поясню:

Форма:

Private WithEvents

Счет As New clsСчет

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Счет.Снятие_со_счета(Val(TextBox1.Text))

End Sub


Private Sub Счет_Не_хватает_денег() Handles Счет.Не_хватает_денег

        Label1.Text = "На счете не хватает денег"



End Sub

Класс:

Public Class clsСчет

    Private Сумма_на_счете As Decimal = 1000

    Public Event

Не_хватает_денег()

    Public Sub Снятие_со_счета(ByVal Сумма_к_снятию As Decimal)

        If Сумма_на_счете - Сумма_к_снятию >= 0 Then

            Сумма_на_счете = Сумма_на_счете - Сумма_к_снятию

        Else

            RaiseEvent

Не_хватает_денег()

        End If

    End Sub

End Class

Пояснения: Вот последовательность действий банковского программиста, пишущего код класса и решившего использовать события:

Сначала он должен придумать событиям подходящие имена и объявить их при помощи слова Event (событие):

    Public Event

Не_хватает_денег()

Затем он должен крепко подумать, в какие моменты выполнения кода его класса должны возникать эти события и во все места кода класса, где оно должно возникать, вставить оператор, порождающий это событие:

            RaiseEvent

Не_хватает_денег()

В нашем случае событием является любая попытка сделать значение переменной Сумма_на_счете отрицательным. Такая попытка предпринята только в одном месте программы, поэтому оператор RaiseEvent встречается только один раз. В больших программах мест в коде, где встречаются соответствующие попытки, может быть несколько. В каждое место нужно будет вставить RaiseEvent.

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

Private WithEvents

Счет As New clsСчет

Когда программист, пишущий код формы, вставит эту строку в код формы, у него в поле, расположенном в верхней левой части окна кода, появится элемент Счет. Для создания обработчика останется только выбрать в поле, расположенном в верхней правой части окна кода, событие Не_хватает_денег этого элемента. Получится заготовка:



Private Sub Счет_Не_хватает_денег() Handles Счет.Не_хватает_денег

Важно понять следующую вещь: Событие не несет в себе никакой информации о том, что именно произошло. В нем ничего нет, кроме его названия. Как тогда программист, пишущий код формы, может быть уверен, что событие Не_хватает_денег возникает именно в тот момент, когда со счета пытаются снять больше, чем там есть? Уверенность может возникнуть только в том случае, если программист, пишущий код класса, пообещает, что так оно и есть на самом деле. Конечно, если код формы и класса пишет один и тот же программист (как в нашем случае), тогда другое дело.

Рассеиваем сомнения. Вы скажете: Того же эффекта можно добиться безо всяких событий, просто написав в коде класса вместо RaiseEvent Не_хватает_денег() оператор, меняющий текст на метке. Но я думаю, магазин не очень будет доволен, что банк протягивает свои длинные руки и так грубо вмешивается во внутренние дела фирмы (то есть формы). Конечно, есть и другие способы решить задачу, но все они хуже. Механизм событий очень гибок и не сует нос в чужие дела. Программисту класса в нашем случае не нужно даже ничего знать о том, как именно на форме будут обрабатывать его событие и будут ли обрабатывать вообще. Его дело – породить событие, а там хоть трава не расти.


Содержание раздела