VB-2012 / 2-cеместр / Дневники / Самостоятельная работа / Лекция 2_2_1 Списки+
.doc-
Создание динамических классов
Рассмотрим классический пример и создадим линейный односвязный список. Для этого определим три класса, задающие:
-
информационную часть элемента списка;
-
структуру элемента списка;
-
сам список, в том числе и операции над ним.
Рассмотрим список, хранящий информацию о личностях.
Создадим вначале класс Личность.
(Смотри его в данном документе Сервис Макросредактор Visual Basic).
Option Explicit
' Создадим класс Личность
' Свойства класса: имя, отчество, фамилию, дату рождения
' Закроем от прямого доступа,
' получить и изменить их можно только через методы класса
Private Имя As String
Private Отчество As String
Private Фамилия As String
Private ДатаРождения As Date
Public Sub InitPerson(ByVal FN As String, ByVal LN As String, _
ByVal DoB As Date)
'Инициализация личности
Имя = FN
Фамилия = LN
ДатаРождения = DoB
End Sub
Public Sub PrintPerson()
'Печать в отладочном окне
Dim s As String
If WhoIs Then s = "родилась" Else s = "родился"
Debug.Print Имя, Отчество, Фамилия, s, ДатаРождения
End Sub
Public Sub CopyPerson(You As Личность)
Имя = You.ВашеИмя
Фамилия = You.ВашаФамилия
ДатаРождения = You.ВашаДатаРождения
End Sub
Public Function WhoIs() As Boolean
' Пытается определить пол личности, анализируя имя и фамилию
' Возвращает True, если думает, что имеет дело с женщиной.
Dim F1 As Boolean, F2 As Boolean
F1 = ПоследняяБуква(Имя) = "А" Or ПоследняяБуква(Имя) = "Я"
F2 = ПоследняяБуква(Фамилия) = "А" Or ПоследняяБуква(Фамилия) = "Я"
If F1 And F2 Then
' можно полагать, что наша Личность - женщина
WhoIs = True
ElseIf Not F1 And F2 Then
WhoIs = False
Else 'Есть сомнения
If Отчество = "" Then
Отчество = InputBox(Имя & " " & Фамилия & "! " & _
"Назовите отчество, пожалуйста.")
End If
WhoIs = ПоследняяБуква(Отчество) = "А"
End If
End Function
Public Sub SayWhoIs()
'Вывод сообщения о поле и возрасте личности
If WhoIs Then
MsgBox ("Думаю, " & Имя & _
", Вы из прекрасной половины человечества!")
ElseIf Year(ДатаРождения) > 1967 Then
MsgBox ("Думаю, " & Имя & ", Вы - молодой человек!")
Else
MsgBox ("Думаю, " & Фамилия & " - мужчина!")
End If
End Sub
Private Function ПоследняяБуква(ByVal W As String) As String
' Внутренняя функция: возвращает в верхнем регистре
' последнюю букву слова W
ПоследняяБуква = UCase(Right(W, 1))
End Function
Public Property Get ВашеИмя() As String
ВашеИмя = Имя
End Property
Public Property Let ВашеИмя(ByVal vNewValue As String)
Имя = vNewValue
End Property
Public Property Get ВашеОтчество() As String
ВашеОтчество = Отчество
End Property
Public Property Let ВашеОтчество(ByVal vNewValue As String)
Отчество = vNewValue
End Property
Public Property Get ВашаФамилия() As String
ВашаФамилия = Фамилия
End Property
Public Property Let ВашаФамилия(ByVal vNewValue As String)
Фамилия = vNewValue
End Property
Public Property Get ВашаДатаРождения() As Date
ВашеОтчество = Отчество
End Property
Public Property Let ВашаДатаРождения(ByVal vNewValue As Date)
ДатаРождения = vNewValue
End Property
Private Sub Class_Initialize()
Имя = "Адам"
Фамилия = "Человек"
ДатаРождения = #1/1/100#
End Sub
Теперь создадим класс с именем ЭлементСпискаЛичностей, задающий структуру элемента (запись). Этот класс прост, поскольку элементы односвязного списка состоят из двух полей – информационного и поля указателя соседнего элемента. Никакие методы над этим классом обычно не определяются.
Его полное описание:
' Класс ЭлементСпискаЛичностей содержит только два поля
Public Сам As Личность
Public Друг As ЭлементСпискаЛичностей
В определении класса ЭлементСпискаЛичностей свойство Друг является объектом того же класса. VB допускает такую рекурсию в определении.
Определим теперь класс СписокЛичностей, задающий сам список. Главное на данном этапе спроектировать операции над списком. Ограничимся набором традиционных методов:
AddFirst (F as Личность) - добавляет элемент в начало списка;
AddLastFirst (F as Личность) - добавляет элемент в конец списка;
Initialize – конструктор по умолчанию, инициализирует список;
PrintList() – печатает содержимое элементов списка;
ClearList() - очищает список.
Таким образом, для построения списка необходимы минимум два указателя – на начало и конец списка: First и Last. Эти свойства закроем от внешнего использования. Добавим к ним открытую переменную Count, следящую за числом элементов списка. Приведем описание свойств и методов этого класса:
Option Explicit
' Определение класса СписокЛичностей
' Свойства
Private First As ЭлементСпискаЛичностей
Private Last As ЭлементСпискаЛичностей
Public Count As Integer
' Методы
Private Sub class_initialize()
Set First = Nothing
Set Last = Nothing
Count = 0
End Sub
Public Sub addfirst(F As Личность)
Dim Elem As New ЭлементСпискаЛичностей
Dim Info As New Личность
' Создаем копию переменной F. В списке будем использовать копию, а не ссылку
Info.CopyPerson F
Set Elem.Сам = Info
Set Elem.Друг = First
If First Is Nothing Then
Set Last = Elem
End If
Set First = Elem
Count = Count + 1
End Sub
Public Sub printlist()
Dim P As ЭлементСпискаЛичностей
Dim Q As Личность
Set P = First
While Not (P Is Nothing)
Set Q = P.Сам
Q.PrintPerson
Set P = P.Друг
Wend
End Sub
Public Sub AddLast(F As Личность)
Dim Elem As New ЭлементСпискаЛичностей
Dim Info As New Личность
' Создаем копию переменной F. В списке будем использовать копию, а не ссылку
Info.CopyPerson F
Set Elem.Сам = Info
Set Elem.Друг = Nothing
If First Is Nothing Then
Set First = Elem
Else
Set Last.Друг = Elem
End If
Set Last = Elem
Count = Count + 1
End Sub
Public Sub clearlist()
' Попытка освободить память не достигает успеха из-за отсутствия
' соответствующего оператора.
Dim P As ЭлементСпискаЛичностей, R As ЭлементСпискаЛичностей
Dim Q As Личность
Set P = First
While Not (P Is Nothing)
Set Q = P.Сам
' unload Q
Set R = P
Set P = P.Друг
' unload R
Wend
' Обнуление указателей
Set First = Nothing
Set Last = Nothing
Count = 0
End Sub
Приведем теперь простой пример, позволяющий построить список в процессе диалога с пользователем и в конце распечатать данные, хранящиеся в построенном списке.
Public Sub ВводСписка()
' Создание списка в диалоге с пользователем
Dim Личности As New СписокЛичностей
Dim ЭтоЛичность As New Личность
Dim Имя As String, Фамилия As String, Дата As Date
If MsgBox("Начнем создавать список личностей?", vbYesNo) = vbYes Then
Do
ЭтоЛичность.ВашеИмя = InputBox("Введите имя личности")
ЭтоЛичность.ВашаФамилия = InputBox("Введите фамилию ")
ЭтоЛичность.ВашаДатаРождения = InputBox("Введите дату рождения ")
Личности.AddLast ЭтоЛичность
Loop Until MsgBox("Продолжим создавать список личностей?", vbYesNo) = vbNo
Личности.printlist
End If
End Sub