:: Меню ::

Головна
  • Про сайт
  • Введення
  • Середовище програмування VB .NET: Visual Studio .NET
  • Вирази, оператори і передача управління
  • Класи і об'єкти
  •  Спадкоємство і інтерфейси
  • Обробка подій і делегати
  • Обробка помилок в VB .NET
  • Форми Windows, графічний вивід і друк
  • Уведення-виведення
  •  Багатопотокові застосування
  • Підтримка баз-даних в VB .NET
  • Короткий огляд ASP .NET
  • Складки .NET, установка додатків і COM Interop
  • Книга для гостей
    Контакти
    Добавити у вибране

    :: Друзі ::

     
     

    :: Лічильники ::

    = =

     

     

     

     

    Знову про властивості

    Принципова відмінність в роботі властивостей Vb6 і VB .NET полягає в тому, що секції Get і Set тепер повинні володіти однаковим рівнем доступу. Визначати властивості з секціями Public Get і Private Set в VB .NET не вирішується.

    Це обмеження легко обходиться. Щоб процедура Set фактично стала закритою, оголосите властивість з атрибутами Public Readonly і одночасно оголосите інше, внутрішня закрита властивість для Set.

    Крім того, в Vb6 властивість не могла змінюватися в процедурі, навіть якщо воно було передане по посиланню (тобто з ключовим словом Byref). У VB .NET властивості, передані по посиланню, можуть змінюватися.

    Але найпринциповіша зміна відноситься до властивостей за умовчанням. У колишніх версіях VB існувала концепція властивостей за умовчанням, яка на перший погляд здавалася дуже зручною. На практиці властивості за умовчанням часто ставали причиною помилок в програмах. Наприклад, що означає наступна команда?

    Me.Text1 = Text2

    Відстежуючи помилки, що виникають в подібних командах, досвідчені користувачі VB з'ясовували, що ця команда задає властивості Text текстового поля з ім'ям Textl значення змінної Text2. Властивості за умовчанням не тільки ставали істоч нікому помилок в програмах, але і вимагали, щоб при привласненні об'єктів використовувалося ключове слово Set, оскільки привласнення об'єктам потрібно було відрізняти від привласнення властивостям. У VB .NET проблема властивостей за умовчанням вирішується просто — вони дозволені тільки там, де це дійсно виправдано, а саме при використанні параметрів. Допустимо, у вас є кеш-таблиця atable; при вибірці значень було б зручно використовувати синтаксис виду atable("thekey"), але це можливо лише в тому випадку, якщо Item є властивістю за умовчанням для класу Hashtable. Властивості за умовчанням оголошуються в класі з ключовим словом Default, причому це допускається лише для властивостей, одержуючих мінімум один параметр. Якщо властивість за умовчанням перевантажується, всі переобтяжені версії також позначаються ключовим словом Default. Властивості за умовчанням найчастіше використовуються за ситуації, коли у об'єкту є властивість, значення якої повертається у вигляді масиву або іншого об'єкту, здатного вміщати декілька величин (наприклад, хэш-таблицы). Припустимо, у вас є клас Sal es і властивість Inyear, яка по отриманому індексу повертає число (об'єм продажів):

    Public Class Sales

    Private m_sales() As

    Decimal = {100, 200. 300}

    Default Public Property Inyear(Byval theyear As Integer) As Decimal

    Get

    Return m_sales(theyear)

    End Get

    Set(Byva1 Value As Decimal)

    m_sales(theyear)=Value

    End Set

    End Property

    ' Решта коду класу End Class

    Властивість за умовчанням дозволяє використовувати конструкції вигляду

    Dim oursales As New Sales()

    Console.WriteLine(oursa1es(1))

    замість

    Dim oursales As New Sales()

    Console.WriteLi ne(oursales.InYear(1))

    Або, наприклад, ви можете написати

    oursales (2) = 3000

    замість

    oursales.InYear(2) = 3000

    Ключове слово Set використовується в процедурах властивостей VB NET.

    Властивості і інкапсуляція

    На перший погляд здається, що властивості дуже схожі на відкриті поля екземплярів. Якщо оголосити в класі А відкрите поле з ім'ям evil, на нього можна послатися за допомогою конструкції A.evil; ніщо не указує на те, що властивість реалізована у вигляді відкритої змінної. Може, визначити відкрите поле і позбавитися від клопоту за визначенням процедур Get і Set?

    Не піддайтеся спокусі. Інкапсуляцію даних не варто порушувати без вагомих причин (а ще краще —те порушувати ніколи!).

    Але інкапсуляцію можна випадково порушити і іншими способами — наприклад, якщо не стежити за повертаними значеннями властивостей. Яким чином? Якщо полем є змінний об'єкт (наприклад, масив), повернення його у вигляді значення властивості приведе до порушення інкапсуляції, оскільки зовнішній код зможе змінити стан поля екземпляра через отриману об'єктну змінну. У таких ситуаціях слід створити клон поля (клонування об'єктів розглядається в розділі 5). Мораль:

    Властивості не повинні повертати змінні об'єкти, які є змінними класів.

    Зона видимості змінних

    Змінні класу (у тому числі і закриті поля), оголошені за межами його методів або властивостей, доступні для всіх членів класу. Змінні, оголошені в методі або властивості, є локальними по відношенню до цього методу або властивості.

    Змінні, оголошені на рівні модуля, доступні для всіх класів, визначених в цьому модулі, і для всієї коди, що володіє доступом до цього модуля.

    Таким чином, змінні рівня модуля є глобальними по відношенню до екземплярів класів. Приклад:

    Module Modulel

    Dim aglobal As Integer = 37

    Sub Main()

    Dim ana As New А()

    Dim ab As New B()

    Console. Readline()

    End Sub

    Public Class A Sub New()

    aglobal =aGlobal +17 Console.WriteLine(aglobal)

    End Sub

    End Class

    Public Class В Sub New()

    Console.WriteLine(aglobal)

    End Sub

    End Class

    End Module

    В даному випадку ціла змінна aglobal визначається на рівні модуля, тому зміни, що вносяться до aglobal класом А, будуть сприйняті класом В. Іспользовать змінні рівня модуля не рекомендується, — вся взаємодія між класами має бути реалізоване на рівні обміну повідомленнями!

    У колишніх версіях VB широко практикувалося зберігання загальних даних класів в глобальних змінних. У VB .NET потреба в цьому небезпечному прийомі відпала. За додатковою інформацією звертайтеся до розділу «Загальні дані в класах» цього розділу.

    Вкладені класи

    У програмах VB .NET нерідко зустрічаються ситуації, коли у вас є два класи: «зовнішній» і «внутрішній», такий, що фактично належить першому. Вкладені (nested) класи зазвичай виконують допоміжні функції, і їх код має сенс лише в контексті зовнішнього класу. Існує хороше емпіричне правило: якщо при прогляданні зовнішнього класу код вкладеного класу можна скрутити у вікні програми і це не утруднить розуміння логіки зовнішнього класу, значить, робота вкладеного класу організована правильно. Звичайно, використання вкладених класів завжди приводить до деякого порушення інкапсуляції — вкладений клас може звертатися до закритих членів зовнішнього класу (але не навпаки!). Якщо ця обставина враховується в архітектурі вашого застосування, не варто приділяти йому особливої уваги, оскільки внутрішній клас всього лише є спеціалізованим членом зовнішнього класу.

    VB .NET не дозволяє розширювати зону видимості вкладеного класу за допомогою функцій. Наприклад, відкритий член зовнішнього класу не може повернути екземпляр закритого або дружнього (Friend) вкладеного класу.

    Практичне використання вкладених класів на прикладі зв'язаного списку

    Вкладені класи найчастіше застосовуються в реалізаціях різних структур даних. До найпоширеніших структур даних належить зв'язаний список. Він є ланцюжком посилань, який дозволяє легко переходити від поточного об'єкту до наступного, проте пошук завжди починається з конкретного посилання. Застосування вкладених класів в реалізації зв'язаного списку виглядає цілком природно, оскільки код об'єктів-посилань не представляє інтересу для користувачів класу Linkedlist, а об'єкти Link не можуть існувати незалежно від об'єкту Linkedlist, що містить їх.

    Нижче приведена дуже проста реалізація класу для роботи із зв'язаними списками. Проглянете її, а потім ми детально проаналізуємо лістинг. Звернете увагу на важливий рядок, виділений жирним шрифтом (рядок 49); у ній використовується нетривіальна особливість об'єктно-орієнтованого програмування, про яку буде розказано нижче.

    1 Option Strict On

    2 Module Modulel 3 Sub Main()

    4 Dim alinkedlist As New Linkedlistc'first link")

    5 Dim aalink As Linkedlist.Link

    6 alink = alinkedlist.MakeLink(alinkedlist.GetFirstLink,"second link")

    7 alink = alinkedlist.MakeLink(alink,"third link")

    8 Console.WriteLine(alinkedlist.GetFirstLink.MyData)

    9 alink = alinkedlist.GetNextLink(alinkedlist.GetFirstLink)

    10 Console.WriteLine(alink.MyData)

    11 Console.WriteLine(alink.NextLink.MyData)

    12 Console. Readline()

    13 End Sub

    14 Public Class Linkedlist

    15 Private m_currentlink As Link

    16 Private m_firstlink As Link

    17 Sub New(Byval thedata As String)

    18 m_currentlink = New Link(thedata)

    19 m_firstlink = in_currentlink

    20 End Sub

    21 Public Function Makelink(Byval currentlink As Link.ByVal

    22 thedata As String) As Link

    23 m_currentlink =New Link(currentlink.theData)

    24 Return m_currentlink

    25 End Function

    26 Public Readonly Property Getnextlink(Byval alink As Link)_

    27 As Link

    28 Get

    29 Return alink.NextLink()

    30 End Get

    31 End Property

    32 Public Readonly Property Getcurrentlink()As Link

    33 Get

    34 Return m_currentlink

    35 End Get

    36 End Property

    37 Public Readonly Property Getfirstunkoas Link

    38 Get

    39 Return m_firstlink

    40 End Get

    41 End Property

    42

    43 ' Вкладений клас для посилань

    44 Friend Class Link

    45 Private m_mydata As String

    46 Private m_nextlink As Link

    47 Friend Sub New(Byval myparent As Link.ByVal thedata As String)

    48 m_mydata - thedata

    49 myparent.m_NextLink = Me

    50 ' End Sub

    51 Friend Sub New(Byval thedata As String)

    52 m_mydata =theData

    53 End Sub

    54 Friend Readonly Property Mydata()As String

    55 Get

    56 Return m_mydata

    57 End Get

    58 End Property

    59 Friend Readonly Property Nextlink()As Link

    60 Get

    61 Return m_nextlink

    62 End Get

    63 End Property

    64 End Class

    65 End Class

    66 End Module

    Рядок 4 створює новий екземпляр зв'язаного списку. У рядку 5 визначається об'єктна змінна типу Link. Оскільки клас Link є вкладеним по відношенню до Linkedlist, його тип записується у вигляді «повного імені» Linkedlist.Link. Рядки 6-12 містять невелику тестову програму.

    У рядках 17-20 визначається конструктор класу Linkedlist, в якому викликається другий конструктор класу Link (рядки 51-53). Останній оголошений з атрибутом Friend і тому доступний для зовнішнього класу Li nkedli st. Якби конструктор Link був оголошений з атрибутом Private, то він став б"и недоступним для зовнішнього класу.

    Також варто звернути увагу на те, як в першому конструкторі класу Link (рядки 47-50) організовується посилання на тільки що створений елемент списку з попереднього елементу. Для цього використовується ключове слово Me — це дуже принциповий момент, тому рядок 49 виділена в лістингу жирним шрифтом. На перший погляд команда myparent.m_NextLink = Me виглядає неприпустимою, оскільки ми звертаємося до закритого поля батьківського класу myparent. Проте програма все-таки працює! Отже, запам'ятаєте дуже важливе правило:

    Для екземпляра класу завжди доступні закриті поля інших екземплярів цього класу.

    При написанні подібних класів в VB .NET можна обійтися і без використання цієї нетривіальної особливості класів. Наприклад, в клас Link можна включити спеціальний метод для створення посилання на наступний елемент списку. Кінець кінцем вибір залежить тільки від вашого стилю програмування. Проте сама можливість звернення до закритих членів класу може піднести неприємні сюрпризи, і про це необхідно знати. З цієї причини в нашому прикладі продемонстрований саме такий підхід.

    Загальні дані в класах

    Повернемося до класу Еmploуєе. Допустимо, кожному працівникові необхідно привласнити унікальний номер. У старих версіях VB завдання вирішувалося за допомогою глобальних змінних, що приводило до порушення інкапсуляції і створювало потенційну загрозу випадкової зміни номерів зовнішнім кодом. Логіка підказує, що номер повинен збільшуватися тільки при створенні нового об'єкту Empl оуєе.

    У VB .NET нарешті з'явилися засоби для досягнення цієї мети. Ідея проста: у класі визначаються дані, спільно використовувані всіма екземплярами даного класу, проте зовнішній доступ до цих даних знаходиться під вашим повним контролем (наприклад, через звернення до властивості). Не варто і говорити, що ці поля ніколи не повинні оголошуватися відкритими...

    Такі поля називаються загальними (shared). Вони ідеально підходять для таких ситуацій, як в нашому призерові з привласненням послідовних номерів. У класах також можуть визначатися загальні властивості і методи. Недолік полягає в тому, що загальні члени класів не можуть працювати із звичайними полями, властивостями або методами. Інакше кажучи, загальні члени працюють тільки з іншими загальними членами. Річ у тому, що загальні дані існують ще до створення об'єкту, тому було б нелогічне дозволяти загальним членам доступ до конкретних об'єктів.

    Нижче приведений фрагмент нової версії класу Employee з використанням загальних даних для привласнення номерів. У класі визначається закрита загальна змінна типу Integer, яка:

    • має початкове значення 1;
    • асоціюється з ReadOnly-свойством, що повертає її поточне значення;
    • змінюється (збільшується) тільки в конструкторі класу.

    В сукупності це означає, що працівникові ніколи не буде привласнений номер 0 і що новий номер виділяється тільки при створенні нового об'єкту Empl oyee — саме це нам і потрібне:

    Public Class Employee

    Private m_name As String

    Private m_salary As Decimal

    Private Shared m_employeeid As Integer = 1

    Public Sub New(Byval thename As String. Byval cursalary As Decimal)

    m_name = thename

    m_salary = cursalary

    m_employeeid = m_employeeid + 1

    End Sub

    Readonly

    Property Employeeld() As Integer

    Get

    Employeeld = m_employeeid

    End Get

    End Property

    End Class

    Нижче приведена невелика програма для тестування класу Empl oyee, а також повний код класу із загальним полем:

    Option Strict On Module Modulel

    Sub Main()

    Dim Tom As New Employee("Tom". 100000)

    System.Console.WriteLine(Tom.TheName & "is employee! " & _

    Tom. Employee ID & "with salary " & Tom.SalaryO)

    Dim Sally As New Employee("Sally". 150000)

    System.Console.WriteLine(Sally.TheName & "is employee!" & _

    Sally.EmployeeID &"with salary "Ssally.Salary())

    System.Console.WriteLine("Please press the Enter key")

    System.Console.Read()

    End Sub

    End Module

    Public Class Employee

    Private m_name As 'String

    Private m_salary As Decimal

    Private Shared m_employeeid As Integer = 1

    Public Sub New(Byval thename As String.ByVal cursalary As Decimal)

    m_name = thename

    m_salary = cursalary

    m_employeeid = m_employeeid + 1

    End Sub Readonly Property Employeeld()As Integer

    Get

    Employeeld = m_employeeid

    End Get End Property Readonly

    Property Thename() As String

    Get

    Thename = m_name

    End Get . End Property Readonly

    Property Salary () As Decimal

    Get

    Salary = m_sa1ary

    End Get

    End Property

    End Class

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

    Не плутайте загальні дані із статичними. Загальні дані існують в одній копії для всіх екземплярів класу, тому з погляду екземплярів вони неявно володіють глобальною видимістю. Статичними називаються змінні, стан яких просто запам'ятовується для повторного використання. Статичними можуть бути оголошені як загальні, так і звичайні поля класу.

     




    :: Наша кнопка ::

    Отримати код:

    Підтримайте наш сайт і розмістіть нашу кнопку на своєму ресурсі.


    :: Реклама ::

    Скачати безкоштовно програму Microsoft Front Page 2003


    :: Посилання ::

    -


     

     

     


    Copyright ©