Обьекты в Visual Basic
Как вы уже несомненно слышали, версии Бэйсика начиная от пятой и выше поддержвают создание почти полноценных обьектов. Почему почти? Потому что полноценнные обьекты должны иметь возможность наследоваться, а также поддерживать инкапсуляцию и полиморфизм. Не поленились посмотреть что я там в словарике написал? Ну, ну. Запомните это - это основа, которую все равно надо знать. Так вот, из трех указанных в Бэйсике, реализовано только два последних. Как-же. как-же закричат любители правды - мы можем сослаться внутри обьекта на методы и свойства другого класса и в результате получить эти самые методы и свойства к использованию, как унаследованные. Правильно, но вы не наследуете обьект - вы наследуете его интерфейсы. И сейчас, давайте лучше плюнем на это - что дано, тем и пользуемся.А начнем мы с самых азов. Что такое класс и как написать свой собственнный первый объект. Класс (а в Бэйсике он реализуеся добавлением в проект class module) это просто шаблон. Некая коробка, на которой большими буквами написано - то что лежит внутри это не просто код, это ОБЪЕКТ! Испугались? Вот и Windows такой надписи пугается, да так сильно, что все, что вы обьявили с волшебным словом Public превращается в свойства или методы объекта. Итак, добавили в проект класс модуль, в свойствах этого класс модуля изменили имя с бестолкового Class1 на MyFirstClass, и смело пишем Public A as integer Возвращаемся в форму, и на Form_load создаем обьект типа MyFirstClass: dim obj as new MyFirstClass И тут справа от точки выпадает список свойств и методов нашего новоявленного объекта. То, что обозначенно пиктограмкой летящего зеленого кирпича - это методы, а листик с перстом указующим - свойства. Запоминаем эти обозначения, с ними вы встретитесь еще не раз, и не только в этом месте. Итак, листик содержит А, АА, ААА Чем между собой отличаются 2 последних ? А ничем, точнее почти ничем - функция может вернуть значение прямо в своем имени, а процедура только в одном или нескольких аргументах. Снаружи они выглядят одинаково, только немного по разному вызываются. Как мы можем использовать класс? Очень просто. Выбирайте один из методов или свойств обьекта obj.aa При этом выполнится код, содержашийся в процедуре АА. Любой объект проходит один раз при рождении через процедуру class_initialaize а при смерти - class_terminate Когда же происходят рождение и смерть Инстанса класса? Рождение (и инициализация) класса происходит при первом вызове метода или свойства объекта. Смерть класса наступает при уничтожении переменной, являющейся референсом (ссылкой на данный обьект - В нашем случае эта переменная obj). Последнее верно до тех пор, пока референс только один Мы дошли до интересного момента - это переменные ссылки на обьект. Вы можете спросить что же в них интересного? А интересного в них - поведение. Вы наверное слышали в детстве от мамы, что присвоить рефреренс объекту просто, надо сказать Set референс_name = Class_Object_name Ключевое слово SET обязательно. Декларация референс_name как обьекта, тоже обязательна. При этом происходит присваивание ссылки объекту (но не создание обьекта). Ссылка на обьект является полноценным "хозяином" этого обьекта, его именем. Зная это имя вы можете манипулировать свойствами, методами, участвовать в эвентах. А что будет если присвоить одной ссылке другую? Set референс2_name = референс_name Вы получите Две одинаковые и равноправные ссылки на обьект - Если убить одну, с самим обьектом ничего не случится. Вот если прибить и вторую... Да, я так вольно толкую о времени жизни этих ссылок. Естественно время жизни переменной оределяется тем, где эта самая преременная обьявленна. Если на General формы - то и умрет вместе с формой, если в процедуре - то по окончанию процедуры. Естественно существует способ убивать обьектные переменные - Set референс_name = Nothing Если референс на обьект(единственный референс) будет перенаправлен на другой обьект - смерти первому обьекту не миновать. Поэкспериментируйте с эвентами Initialize & Terminate класса, поместив туда мессадж боксы. Теперь про волшебное слово NEW - оно меняет смысл указанных выше присвоений Set референс_name = New Class_Object_name При этом вы создаете не ссылку на существующий обьект , а ссылку на Новую Инстанс этого обьекта. Сам этот несуществующий обьект еще не родится, (родится он при первом же обращении к свойствам или методам) но ссылка уже будет подготовлена. Так же как и раньше вы можете иметь несколько ссылок на один обьект (родившийся или не родившийся), но использование слова NEW создаст вам еще одну копию (инстранс). Ну и напоследок - ссылка это все-таки не класс из которого рожден обьект, поэтому конструкция типа Set референс2_name = NEW референс_name - вызовет ошибку времени выполнения. 05 Ноября 1998г. Обещанное продолжение:Начну , пожалуй с того , что открою вам тайну. Даже две. Первая, наиболее страшная, это то, что обьекты внутри состоят из обычного кода, который вы лихо лепите тысячами строк. Т.е. не надо ожидать увидить внутри классов что-то, чего вы не видите в обычных формах . Кстати, как дополнение к этой страшной тайне - формы, такие привычные и любимые нами формы - это тоже инстансы классов. Предопределенные заранее, уложенные в коллекцию форм, но в то же время просто объекты. Думаю к последнему факту мы еще вернемся. Интуитивно ясно, для чего предназначенны эти процедуры. Let - установить значение свойства , Get - получить у обьекта установленное значение, Set - то же что и первое, только для свойства типа объект. Предвижу вопросы типа "А зачем это вообще нужно? Мы легко создаем свойства объявляя в классе Public переменные." Да. Вы действительно можете, и обязательно будете это делать - только такие свойства - статические. Максимум на что они годятся - это хранить значения. Чаще же изменение значения свойства влечет за собой какое либо действие. Давайте рассмотрим тривиальный пример - наша форма [ Еще помните про первую тайну :-) ? ] уже имеет свойство StartUpPosition, однако это такое "одноразовое" свойство. Создадим нашему обьекту-форме еще одно свойство - Center. Это простое свойство будет иметь всего 2 значения - Да и Нет (boolean). В случае установки этого свойства в True Форма должна изменить свое положение, и переместится в центр экрана. В случае установки этого свойства в False Форма должна "вспомнить" свое прошлое положение.Для приготовления этого блюда вам понадобится кастрюля, свежее мясо... Впрочем отвлекся я куда-то в сторону. Так вот нам понадобится вспомнить про вторую тайну. Т.е. форма изнутри - совсем не обьект, и для обращения с ней, как с обьектом вам нужна вторая форма, чтобы "смотреть" на первую "снаружи". А внутри формы нужно добавить две переменные для хранения координат формы (мы ведь собираемся из восстанавливать по False), и Property Let & Property Get Последние две проще всего добавить так - откройте окно кода, затем выберите в меню Tools Бэйсика "Add Procedure", надписать Center, пометить Property и Public. После Ok, вы увидите в коде две новые процедуры. Public Property Get Center() As Variant Что такое vNewValue? Собственно, это переменная, которая будет принимать значение передаваемое в свойство. Эта переменная Должна быть того же типа что и сам аргумент принимаемый и возвращаемый свойством. Естественно и Property Get Center должно быть того же типа. Так что меняем оба Variant на Boolean Option Explicit Public Property Get Center() As Boolean Public Property Let Center(ByVal vNewValue As Boolean) Добавьте вторую форму, на нее 2 кнопки, и код Option Explicit Private Sub cmdCenter_Click() Private Sub cmdNonCenter_Click() Private Sub Form_Load() Да, не забудьте в свойствах проекта указать Startup Form - Form2Рекомендую поставить точки останова , и посмотреть как это точно работает. Да, в списке свойств Fom1 появилось только одно свойство Center, хотя процедур 2. Также не видны и три наши переменные. Теперь вы легко догадаетесь, как сделать свойство "только для чтения" или "только для записи"- правильно - стереть ненужную процедуру. И, помните событие class_initialaize? Это самый удобный момент присвить переменной blnCenter значение по умолчанию (соответсвенно и свойство будет иметь такое же значение. Ну, а в качестве домашнего задания сделате метод SlowMove, которые медленно и плавно двигает форму в указанную точку, и свойство Proporcional - несущее отношение высоты формы к ширине. Что то , связанное со свойствам осталось непонятным? Пишите вопросы- буду дописыватьСобственно, появилось дополнение, и чтобы не вводить вас в заблужедение, я должен о нем сказать - внутри обьекта вы можете обратиться к самому обьекту использую псевдоним Me. Поставленная после Ме точка подсветит вам все существующие свойства и методы обьекта. 28 Ноября 1998г Обещанное продолжение:Обьекты изнутри. Тайну эту я вам уже выболтал в прошлом выпуске. Там внутри просто код. Ну и соотвественно все , что мы можем делать в обычном коде - можем и там. Какие возможности открывает перед нами запихивание кода в класс? А разные! Вот например такая задачка. Всем хороши коллекции. Но нередко необходимо ограничить количество элементов. Можем мы это сделать в оригинальной коллекции? Нет, не можем. Мы не в состоянии влезть внутрь реализованных встроенных свойств и методов. Зато мы можем написать собственный класс. Вот и давайте быстренько это сделаем. Добавить класс модуль Назвать его MyCol Создать Private переменную типа New Collection Тут стоп. Почему Private? Потому что нам не надо , чтобы коллекцию было видно снаружи. Почему New Collection? Потому что иным способом обьявить коллекцию нельзя. Можно создать ссылку на существующую коллекцию, но не более. А нам нужна новая. Создать методы Remove, ADD, Item, Count - первая как процедура, последние 3 как функции. Начнем с простой - Count : Public Function Count() As Long Аналогично создаются и остальные - просто повторяете матоды коллекции, принимая их аргументы. Остановимся на ADD: Public Function Add(Item As Variant, Key As String) As Boolean Итак, обратите внимание - функция возвращает True только если добавить удалось. Если не удалось - ложь. Второе - первый аргумент обьявлен как variant - очень удобно, можно передать и строку, и число, и даже обьект. И это не всегда плюс - тут у вас в руках еще один механизм ограничениий - измените тип переменной, и получите коллекцию кнопок или строк, или... В этом примере количество элементов, допустимых к добавлению - зашито в коде - а это как то не к лицу нашему универсальному классу. Пэтому давайте добавим Public свойство NumberOfItem, и на всякий случай зададим ему значение по умолчанию, и сделаем это в событии class_initialaize: NumberOfItem = 32000 (Число - чисто к примеру, и ничего не означает) Еще необходимо осветить один момент, Что делать с ошибками? Конечно, если кода так мало - как в нашем примере - то все можно предусмотреть, и ошибок времени выполнения успешно избежать. Если же код большой, то и возможность появления этих ошибок растет. Необходимы обработчики ошибок . Эти обработчики прекрасно делают свое дело - если вы пишете просто классы, которые встраиваются в ваш проект, а не оформляются в виде отдельных модулей exe (серверов) Правда до этого вам надо почитать по поводу создания и регистрации внешних модулей. Кое что я писал об этом в "DCOM или Компоненты типа Клиент-Сервер", скорее всего я размещю аналогичный материал и здесь. Но это тема для нашего следующего "урока". 28 декабря 1998г Обещанное продолжение: Инстансы Обьектов. Мы говорили уже о разных способах создания обьектов. Вы уже обращали внимание на то, что в разных случаях (тип библлиотеки класса exe или dll, значение свойства public ) свойство Instansing имеет различные доступные значения. Это естественно, так как это свойство определяет какой конретно тип доступа к экземплярам класса будет назначен. 1 - Private Далее мы поговорим о: PS. Я ничего не пишу здесь об UserControls. Это тема для другого большого разговора. И, к тому же, 9/10 всех моих попыток написать свой собственный юзерконтрол приводили к тому, что я задумавшись над предстоящей работой понимал - лучше этого не делать. Много труда придется вложить, а реальная польза от написанного не всегда настолько очевидна. К тому же нередко такой контрол за тебя уже написан. Я не навязываю этот свой опыт - Юзерконтролы модный инструмент, но однако - Думайте перед написанием кода. Делайте это всегда :-) Удачи! Словарик терминов Наследование Инкапсуляция Полиморфизм Методы Интерфейс Инстанс класса Коллекции
Страница сайта http://silicontaiga.ru
Оригинал находится по адресу http://silicontaiga.ru/home.asp?artId=6478 |