Обьекти в Visual Basic

Коротко про створення, застосування, властивості

Борис Рудой

Хочу відразу попередити – то що ви будете читати тут – ні в якому разі не є академічним описом об’єктно орієнтованого програмування. Більше того – це не можна назвати навіть нормальної навчальної статтею. То про що я буду писати найімовірніше вже вам знайомо, чи ви про все це здогадувалися. У той же час так, не зовсім традиційно викладена інформація може в якійсь мірі прояснити вам картину бачення обьектов, крізь призму Visual Basic. Так що – Вперед!

Як ви вже безсумнівно чули, версії Бейсік починаючи від п’ятої та вище поддержвают створення майже повноцінних обьектов. Чому майже? Тому що полноценнние обьекти повинні мати можливість успадковуватися, А також підтримувати інкапсуляцію і поліморфізм. Не полінувалися подивитися що я там в словничок написав? Ну, ну. Запам’ятайте це – це основа, яку всі одно треба знати. Так от, із трьох зазначених у Бейсік, реалізовано тільки два останніх. Як-же. як-же закричать любителі правди – ми можемо послатися всередині об’єкта на методи і властивості іншого класу і в результаті отримати ці самі методи і властивості до використання, як успадковані. Правильно, але ви не наслідуєте обьект – ви наслідуєте його інтерфейси. І зараз, давайте краще плюнемо на це – що дано, тим і пользуемся.А почнемо ми з самих азів. Що таке клас і як написати свій собственнний перший об’єкт.
Клас (а в Бейсік він реалізуємо додаванням в проект class module) це просто шаблон. Якась коробка, на якій великими літерами написано – То що лежить всередині це не просто код, це ОБ’ЄКТ! Злякалися? Ось і Windows такого напису лякається, та так сильно, що все, що ви обьявили з чарівним словом Public перетворюється на властивості або методи об’єкта. Отже, додали в проект клас модуль, у властивостях цього клас модуля змінили ім’я з нетямущого Class1 на MyFirstClass, і сміливо пишемо

Public A as integer
Public Sub AA ()
End Sub
Public Function AAA() as integer
End function

Повертаємося у форму, і на Form_load створюємо об’єкт типу MyFirstClass:
dim obj as new MyFirstClass
obj.
І тут праворуч від точки випадає список властивостей і методів нашого новоявленого об’єкта. Те, що позначення піктограмкой летить зеленого цегли – Це методи, а листочок з перстом вказівним – властивості. Запам’ятовуємо ці позначення, з ними ви зустрінетеся ще не раз, і не тільки в цьому місці. Отже, листик містить А, АА, ААА Чим між собою відрізняються 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 – викличе помилку часу виконання.

Обіцяне продовження: Почну, мабуть з того, що відкрию вам таємницю. Навіть дві. Перша, найбільш страшна, це те, що об’єкти всередині складаються із звичайного коду, який ви хвацько ліпіть тисячами рядків. Тобто не треба очікувати побачити всередині класів щось, чого ви не бачите в звичайних формах. До речі, як додаток до цієї страшної таємниці – форми, такі звичні й улюблені нами форми – це теж інстанси класів. Зумовлені заздалегідь, укладені в колекцію форм, але в той же час просто об’єкти.
Думаю до останнього факту ми ще повернемося.
Друга таємниця, якимсь невловимим чином теж пов’язана з першою, полягає в тому, що зсередини класу – обьект (інстанси цього класу), як такої – Не видно. Його там (всередині клас модуля) не існує і існувати не може. Зате ооттуда ви легко можете отримати доступ до всіх властивостей і методам, так як це, не більш ніж змінні, процедури і функції. З того, що не зустрічалося вам у звичайному програмуванні можна відзначити спеціальні процедури – Property Let, Property Get, Property
Set.

Інтуїтивно ясно, для чого призначені ці процедури. 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
End Property
Public Property Let Center(ByVal vNewValue As Variant)
End Property

Що таке vNewValue? Власне, це змінна, яка буде приймати значення передане в властивість. Ця змінна Повинна бути того ж типу що і сам аргумент приймається і повертається властивістю. Природно і Property Get Center повинно бути того ж типу. Так що міняємо обидва Variant на Boolean
Далі нам потрібні дві Private змінні MyLeft і MyTop (long), і ще одна, щоб пам’ятати яке ж значення цієї властивості встановлено зараз – blnCenter (boolean) Остання потрібна так само для передачі цього значення між Let та Get. Ось що вийде:

Option Explicit
Dim MyTop As Long
Dim MyLeft As Long
Dim blnCenter As Boolean

Public Property Get Center() As Boolean
     Center = blnCenter
End Property

Public Property Let Center(ByVal vNewValue As Boolean)
      blnCenter = vNewValue
      If blnCenter Then
      MyTop = Me.Top
     MyLeft = Me.Left
     Me.Top = (Screen.Height – Me.Height) / 2
     Me.Left = (Screen.Width – Me.Width) / 2
Else
     Me.Top = MyTop
     Me.Left = MyLeft
     End If
End Property

Додайте другу форму, на неї 2 кнопки, і код

Option Explicit
Dim obj As New Form1

Private Sub cmdCenter_Click()
     obj.Center = True
End Sub

Private Sub cmdNonCenter_Click()
     obj.Center = False
End Sub

Private Sub Form_Load()
     obj.Show
     obj.Left = 500
     obj.Top = 1000
End Sub

Так, не забудьте у властивостях проекту вказати Startup Form – Form2Рекомендую поставити крапки останова, і подивитися як це точно працює.
Так, у списку властивостей Fom1 з’явилося тільки одна властивість Center, хоча процедур 2. Також не видні і три наші змінні. Тепер ви легко здогадаєтеся, як зробити властивість “тільки для читання” або “Тільки для запису” – правильно – стерти непотрібну процедуру. І, пам’ятайте подія class_initialaize? Це найзручніший момент присв змінної blnCenter значення за замовчуванням (соответсвенно і властивість буде мати таке ж значення. Ну, а в якості домашнього завдання сделат метод SlowMove, які повільно і плавно рухає форму в вказану точку, і властивість Proporcional – несуче відношення висоти форми до ширини. Що то, пов’язане зі властивостям залишилося незрозумілим? Пишіть питання-буду допісиватьСобственно, з’явилося доповнення, і щоб не вводити вас в заблужеденіе, я повинен про нього сказати – всередині обьекта ви можете звернутися до самого обьекту використовую псевдонім
Me.
Поставлена ​​після Ме точка підсвітить вам всі існуючі властивості і методи об’єкта.

Обьекти зсередини

Таємницю цю я вам уже вибовкав в минулому випуску. Там всередині просто код. Ну і соотвественно все, що ми можемо робити в звичайному коді – можемо і там. Які можливості відкриває перед нами запихання коду в клас? А різні! Ось наприклад така задачка. Всім хороші колекції. Але нерідко необхідно обмежити кількість елементів. Можемо ми це зробити в оригінальної колекції? Ні, не можемо. Ми не в змозі влізти всередину реалізованих вбудованих властивостей і методів. Зате ми можемо написати власний клас. Ось і давайте швиденько це зробимо.

  1. Додати клас модуль
  2. Назвати його MyCol
  3. Створити Private змінну типу New Collection
    Тут стоп. Чому Private? Тому що нам не треба, щоб колекцію було видно зовні. Чому New Collection? Тому що іншим способом обьявить колекцію можна. Можна створити посилання на існуючу колекцію, але не більше. А нам потрібна нова.

Створити методи Remove, ADD, Item, Count – перша як процедура, останні 3 як функції. Почнемо з простої – Count:

Public Function Count() As Long
     Count = Col.Count
End Function

Аналогічно створюються і решта – просто повторюєте матоди колекції, приймаючи їх аргументи. Зупинимося на ADD:

Public Function Add(Item As Variant, Key As String)
As Boolean
     if Col.Count <=5 Then
          Col.Add Item, Key
          Add = true
     Else
          Add = False
     end if
End Function

Отже, зверніть увагу – функція повертає True тільки якщо додати вдалося. Якщо не вдалося – брехня. Друге – перший аргумент оголошено як variant – дуже зручно, можна передати і рядок, і число, і навіть обьект. І це не завжди плюс – тут у вас в руках ще один механізм Обмеження – змініть тип змінної, і отримаєте колекцію кнопок або рядків, або …
Так, ви можете запитати як на рахунок необов’язкових параметрів Before і After в нашому цьому методі. Хороший Питання. Почитайте відповідь в хелпе на IsMissing і Optional Arguments

У цьому прикладі кількість елементів, допустимих до додаванню – зашито в коді – а це як то не до лиця нашому універсальному класу. Петому давайте додамо Public властивість NumberOfItem, і на всяк випадок задамо йому значення за замовчуванням, і зробимо це в подію class_initialaize: NumberOfItem = 32000 (Число – чисто наприклад, і нічого не означає) Ще необхідно висвітлити один момент, Що робити з помилками? Звичайно, якщо коду так мало – як у нашому прикладі – то все можна передбачити, і помилок часу виконання успішно уникнути. Якщо ж код великий, то і можливість появи цих помилок зростає. Необхідні обробники помилок. Ці обробники чудово роблять свою справу – якщо ви пишете просто класи, які вбудовуються в ваш проект, а не оформляються у вигляді окремих модулів exe (серверів)
Якщо вам треба повернути помилку в зухвалу програму, то можуть виникнути складності – в цьому випадку потрібно використовувати Rise метод Err обьекта. Рекомендую вам спробувати це ручками.
Правда до цього вам треба почитати з приводу створення і реєстрації зовнішніх модулів. Кое что я писав про це в "DCOM або Компоненти типу Клієнт-Сервер “, Швидше за все я розміщу аналогічний матеріал і тут. Але це тема для нашого наступного “уроку”.

Інстанси обьектов

Ми говорили вже про різні способи створення об’єктів. Ви вже звертали увагу на те, що в різних випадках (тип біблліотекі класу exe або dll, значення властивості public) властивість Instansing має різні доступні значення. Це природно, тому що це властивість визначає який конретно тип доступу до екземплярів класу буде призначений.

Для VB6 це властивість буде мати 6 різних значень:

1 – Private
Примірники цього класу не можуть бути створені ізвне.Более того вони ззовні не видно Ви можете створювати і використовувати такі обьекти тільки зсередини проекту, в котрому “сидить” цей клас модуль.

2 – PublicNotCreatable.
Примірники цього класу теж не можуть бути створені ззовні, проте вони можуть бути використані якщо вже створені “зсередини”.

3 – SingleUse.
Ви можете використовувати CreateObject function або ключове слово New для створення екземплярів цього класу. При цьому кожен новий елемент класу буде стартувати в окремому “робочому просторі” Ця властивість не з’являється, якщо ви створюєте ActiveX DLL. Зверніть увагу ви таки можете настворювали хоч сотню екземплярів цього класу.

4 -GlobalSingleUse.
Префікс Global означає, що використовувати цей тип класу можна без додатковий обьявлений. В іншому це те ж саме що і 3

5 – MultiUse.
Так, саме, ви можете створювати і використовувати екземпляри цього класу звідусіль, при цьому допустимо, що одна фізична копія об’єкта в пам’яті буде обслуговувати всі створені екземпляри. Деякі проблеми, пов’язані з використанням цієї властивості (відмова в коректній роботі при певних налаштуваннях DCOM) я расcматрівал в статті про налаштуванні DCOM компонентів

6 – GlobalMultiUse.
Префікс Global означає, що використовувати цей тип класу можна без додатковий обьявлений, т.е клас створюється автоматично, ви можете відразу використовувати його властивості та методи як глобальні функції. . В іншому це те ж саме що і 5

Далі ми поговоримо про:
Створення Евентов класу.

PS. Я нічого не пишу тут про UserControls. Це тема для іншої великої розмови. І, до того ж, 9/10 всіх моїх спроб написати свій власний юзерконтрол приводили до того, що я задумавшись над майбутньою роботою розумів – краще цього не робити. Багато праці доведеться вкласти, а реальна користь від написаного не завжди настільки очевидна. До того ж нерідко такий контрол за тебе вже написаний. Я не нав’язую цей свій досвід – Юзерконтроли модний інструмент, але проте – Думайте перед написанням коду. Робіть це завжди 🙂 Удачі!

Словничок термінів

Спадкування

Означає те, що один обьект може бути побудований на базі іншого. при цьому можуть бути успадковані властивості, методи і події. До прикладу клас магнітофон – це щось вміє програвати музику з аудіо касет. На його основі можна побудувати клас плеєр – заховати властивість “запис” і мінімізувати властивості “розмір” і “вага” (жартую – Але ідеологічно правильно)

Інкапсуляція

Інкапсуляцію можна трьома словами описати так обьект це “річ в собі “. Тобто інформація про обьекте – його властивості та методи містяться в описі цього об’єкта. Якщо повернутися до нашого магнітофону – То в опис магнітофона входить, наприклад “двохкасетною дека “, з тюнером і приймачем FM. Методами в даному випадку будуть: перемотати стрічку, відтворювати, записувати.

Поліморфізм

Поліморфізмом називають здатність багатьох обьектов використовувати один і той же метод. При цьому вироблені дії будуть залежати від того, якого типу обьект їх ініціював. З магнітофоном тут приклад не піде 🙂 А ось з Бейсік – будь ласка. Майже всі контроли в Бейсік мають метод SetFocus, але передаватися він буде саме того контролю, який його викликав. І у випадку з кнопкою – це викличе появу рамки, а у випадку з текстбоксом – перенесення курсора.

Методи

Методи це в принципі те, як ваш обьект реагує на події .. Повертаючись до вже обридлому магнітофону – ви просто нажімете кнопку Play (це подія) далі магнітофон починає прокручувати плівку, посилювати сигнал … Вам вже не треба пояснювати йому що робити далі.

Інтерфейс

Інтерфейсом для обьекта можна назвати набір пов’язаних властивостей і методів

Інстанси класу

Інстанси називається одна копія обьекта завантажена в пам’ять. Одночасно в пам’яті може існувати багато інстанси одного об’єкта.

Колекції

Колекції – як зрозуміло з назви, це набір елементів, зібраний в купу. Тип елементів не істотний. Доступ до елементів здійснюється по текстовому унікальному ключу. Цей ключ присваевается елементу при додаванні в колекцію. Так само до будь-якого елементу колекції можна дістатися послідовним перебором.

[Вперед]

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*