| FAQ по Visual Basic |
| Содержание / Начальные сведения о VB |
|
|
§ 3.3. Что такое классы и с чем их едят?
Тема эта столь обширна и затрагивает так много областей программирования, что ей место не в кратеньком FAQ'е, а в обстоятельной книжке. Но я попробую совместить несовместимое, и надеюсь, гуру не будут в обиде, если я опущу частности и то, что мне показалось неважным. Что такое класс? Это совокупность методов, свойств и событий, которые образуют целостный объект. А теперь попроще. Объект — наручные часы. Методы предназначены для установки времени на часах, установки будильника и т. д. Свойства, в нашем случае, определяют цвет корпуса, вид индикатора и т. д. Звук будильника является событием и позволяет провести определенные действия (например, снять молоко с плиты) в заданное время. Чтобы получить доступ к свойствам, методам и событиям объекта (часов), необходимо создать указатель на него, или инстанс. Если класс называется Clock, то создание экземпляра класса (инстанса) будет выглядеть так: Dim clk As Clock Set clk = New Clock При необходимости можно создать несколько экземпляров одного и того же класса, и все эти экземпляры будут работать независимо друг от друга. Ну а теперь, чтобы вызывать метод или обратится к свойству класса, пишем: ' вызовем метод установки времени clk.SetTime "13:56" ' а теперь изменим свойство "Цвет корпуса" clk.Color = "Gold" ' или увеличим свойство "Цена" на 1000 баксов ;-) clk.Price = clk.Price + 1000 А теперь самое сложное: создание классов. Начнем с азов.
Добавить модуль класса (часто его называют классовым модулем)
можно посредством меню Очень часто, создавая переменные или процедуры, приходится решать вопрос: можно ли будет их использовать вне модуля, или они необходимы только самому модулю. В первом случае такие процедуры или переменные объявляются с префиксом Public, а во втором случае — с префиксом Private. Префикс Public является умолчательным, и хотя его можно опускать, я рекомендую этого не делать. Добавьте в проект простой, не классовый, модуль и наберите в нем: ' эта переменная видна снаружи модуля Public MyFirstVar As Integer ' а эта переменная является приватной ' и не видна вне модуля Private MySecondVar as Integer Создайте в том же модуле процедуру CheckVar и обратитесь из нее к этим двум переменным:
Public Sub CheckVar()
MyFirstVar = 5
MySecondVar = 7
End Sub
Это удается без труда. А теперь обратимся из модуля
формы (он по умолчанию уже входит в проект)
к созданным переменным. Как видим, вторая переменная
не существует для всего мира Методы — это уже знакомые вам процедуры (sub) и функции (function). Метод может иметь аргументы, а может не иметь их. Если метод построен на основе функции, то он способен возвращать значения. Создадим метод установки времени на наших часах и метод, возвращающий информацию о состоянии батарейки питания. Для этого в модуле класса напишем: ' переменная для хранения времени Private m_Time As String ' публичный метод установки времени Public Sub SetTime(a_Time As String) ' запомним значение m_Time = a_Time ' произведем какие-то действия . . . End Sub ' публичный метод, возвращающий напряжение ' батарейки питания Public Function GetPowerState () As Single ' определим напряжение питания батарейки . . . ' просто эмуляция работы некоего кода BatteryVoltage = 1.48 ' возвратим значение GetPowerState = BatteryVoltage End Function Создав инстанс класса (как было показано в начале статьи), обращаемся к новоиспеченным методам: Dim sTime As String ' установим время sTime = InputBox ("Введите текущее время:", _ "Часики", "18:16") clk.SetTime sTime ' определим состояние батарей ' в окне будет напечатано 1,48 MsgBox clk.GetPowerState() Условно говоря, свойство очень условно можно представить как пара состоящая, из функции и процедуры с одним и тем же именем. При обращении к свойству вызывается функция, при изменении — процедура. Если отойти от условностей, то для создания свойств существует ключевое слово Property с суффиксом Get для получения значения и с суффиксом Let или Set (для объектов) для установки значения. Вообще, свойство чем-то похоже на объявленную публичную переменную. С тем лишь отличием, что изменение значения такой переменной нельзя отследить, как и нельзя отследить обращения к этой переменной. Свойства же позволяют это реализовать. И все-таки, зачем нужны свойства? Почему бы вместо них не обойтись знакомыми процедурами и функциями? Предположим, наш класс должен иметь возможность выдавать стоимость часов и позволять эту стоимость изменять. Реализовать это проще простого: Public Price As Single Тогда обращение к этой переменной извне выглядит так: ' установить стоимость часов clk.Price = 500 ' выдать стоимость часов MsgBox clk.Price Поставим задачу. Пользователь не должен иметь возможности установить цену ниже 150 и выше 800 долларов. Переменная с этим справиться неспособна. Берем на помощь процедуры и функции: Private m_Price As Single ' процедура получения цены Public Function GetPrice() As Single GetPrice = m_Price End Function ' процедура установки цены Public Sub SetPrice(a_Price As Single) If a_Price <= 800 And a_Price >= 150 Then m_Price = a_Price End If End Sub Можно так написать? Можно. Все будет работать, но возникает ощущение некоей громоздкости, нерациональности: ' установить стоимость часов clk.SetPrice 450 ' выдать стоимость часов MsgBox clk.GetPrice И тут на помощь приходят свойства: Private m_Price As Single ' свойство получения цены Public Property Get Price() As Single Price = m_Price End Property ' свойство установки цены Public Property Let Price(ByVal a_Price As Single) If a_Price <= 800 And a_Price >= 150 Then m_Price = a_Price End If End Property Обращение к свойству выглядит так: clk.Price = 500 ' установить стоимость часов MsgBox clk.Price ' выдать стоимость часов Не правда ли, похоже на обращение к переменной? Последнее, что нужно знать о свойствах. Вы можете создавать свойство, состоящее только из Property Get или Property Let (Property Set). В первом случае свойство будет только для чтения, т. е. неподдающимся для изменения, а во втором случае вы сможете установить свойство, но не прочитать его.
События (Events, ивенты) позволяют строить асинхронные модели,
когда объект формирует и выстреливает Итак, создадим новый ивент в нашем классе Clock: ' декларируем публичный ивент Public Event Alarm(Melody As String) ' некая приватная процедура, генерирующая ивент Private Sub GenerateAlarm() ' некоторые действия . . . ' выстреливаем ивент RaiseEvent Alarm("My little star.") End Sub Для того, чтобы иметь возможность получать ивенты, внесем некоторые изменения в код создания экземпляра класса. Для этого воспользуемся новым ключевым словом WithEvents: Dim WithEvents clk As Clock Set clk = New Clock Если теперь в окне модуля, где создавался инстанс, раскрыть левый комбобокс, то в списке объектов окажется слово clk. Установив его, в списке ивентов правого комбобокса найдем ивент Alarm: Private Sub clk_Alarm(Melody As String) End Sub Всякий раз, когда будет выстреливаться ивент Alarm, управление будет передаваться на этот участок кода, в котором можно выводить окно или играть подходящий wav файл. А теперь перейдем от теории к практике и поставим новую задачу. Предположим, вы работаете в банке и ваш работодатель заказал вам написание управляющей программы для банкомата. Опустим все малозначащие детали и сформулируем требования к программе:
Подойдем к этой задаче, вооружившись знаниями о классах. Для этого разнесем интерфейс программы и код, ведающий обработкой данных. Последний поместим в класс.
Создадим новый проект и назовем его CreditCard.
Добавим к проекту класс CCard. Этот класс будет ведать
работой с банком. Управлять классом будет форма, названная
winCard. Подобное разделение на независмые блоки
полезно тем, что изменяя интерфейс, вы не трогаете класс,
ведающий обработкой данных. А в случае изменения способа
обмена с банком можно легко заменить класс на другой,
не трогая интерфейс, столь полюбившийся клиентам. Для начала разберемся с классом. Он должен содержать метод Connect подключения к серверу банка и метод Disconnect отключения от сервера. Метод Connect должен возвращать True в случае успеха и False, если соединение не прошло. Свойство Account возвращает сумму в банке на счету клиента. Для изменения остатка на счету служит уже другой метод — Change. В случае успеха метод возвращает True, и если транзакция пройти не может (со счета снимают больше, чем он содержит) — False. К интерфейсу нет особых требований. Он должен обеспечивать подключение и отключение клиента (2 кнопки), предоставлять клиенту информацию о состоянии его счета (поле Label) и позволять клиенту изменить сумму на счету (поле TextBox и кнопка). Вы можете изменить интерфейс как вам заблагорассудится, но это не должно отразиться на работоспособности программы. А теперь, зная задачу, попробуйте самостоятельно ее выполнить.
Для тех, кто не до конца понял объяснений данной
статьи, работающий пример проекта находится
в архиве
Автор: |
||
| Предыдущий раздел | Следующий раздел |
| © 2004. При цитировании, пожалуйста, не забудьте поставить ссылку на оригинальную страницу. |