Классы - Международный банковский институт

advertisement
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Практическая работа по теме 7. Архитектура и
возможности семейства языков высокого уровня
Описание свойств класса, как открытых или закрытых переменных.
Использование конструкторов класса. Ограничение доступа к
свойствам. Разделяемые переменные в классах. Тестирование
классов. Синхронизация элементов управления формы. Классы
работы с векторами и простыми дробями.
Практическая работа по теме 7. Архитектура и возможности семейства языков высокого
уровня .............................................................................................................................................1
Задание 1. Описание свойств класса, как открытых переменных ........................................1
Задание 2. Описание свойств класса, как закрытых переменных ........................................7
Задание 3. Использование конструкторов класса ................................................................10
Задание 4. Ограничение доступа к свойствам класса ..........................................................11
Задание 5. Разделяемые переменные в классах ....................................................................14
Задание 6. Синхронизация элементов управления...............................................................16
Задание 7. Создание класса Vector (свойства класса) ..........................................................18
Задание 8. Работа с простыми дробями.................................................................................19
Задание 9. Печатающаяся строка ...........................................................................................20
Задание 1. Описание свойств класса, как открытых
переменных
Задача
Обеспечить хранение данных класса (свойств класса) в открытых
переменных, то есть переменных, доступных объектам текущего
класса или объектам других классов.
Решение
При описании свойств класса необходимо использовать ключевое
слово (модификатор) Public.
Обсуждение
Класс является базовым понятием в объектно-ориентированном
программировании. Класс, представляющий собой некоторый набор
свойств
(количественных
или
качественных
описательных
характеристик объекта), методов (процедур и/или функций) и событий,
происходящих или не происходящих при выполнении методов класса,
может быть описан как в отдельном библиотечном файле с
последующим подключением к проекту, так и непосредственно в
одном из модулей текущего проекта.
В любом случае, описание класса в VB.NET следует выполнять в
отдельном модуле, который создается через меню Project– Class
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Module. Имя класса лучше указывать сразу – при открытии модуля
класса. Описание нового класса выполняется внутри следующей
конструкции:
Public Class ИмяКласса
Описание класса:
Описание свойств класса
Описание методов класса
Описание событий класса
End Class
Требуемое поведение объектов класса обеспечивается при помощи
методов, свойств и событий, описанных в модуле класса. Этот
процесс называется инкапсуляцией. Инкапсуляция – один из базовых
принципов объектно-ориентированного программирования, наряду с
полиморфизмом и наследованием. Все, что определяет класс, как
единую структуру, должно размещаться в модуле класса под единым
именем – именем класса.
Свойства
класса
представляют
собой
переменные,
инкапсулированные в структуру класса. Свойства описываются как
переменные разных типов и разной области видимости (scope).
Свойства класса могут быть описаны одним из способов: или как
переменные класса с областью видимости Public, или как
переменные класса с областью видимости Private. В любом случае
эти переменные будут хранить значения свойств экземпляров класса.
Public|Private ИмяСвойства As TypeObject
Имена свойств, также как и имена переменных, должны подчиняться
принятым ограничениям на использование допустимых символов. Имя
свойства должно быть коротким, но достаточно значащим,
позволяющим любому другому программисту интуитивно понять
назначение свойства.
Не забывайте, что одним из основных достоинств объектноориентированного
программирования
является
повторное
использование кода описания классов.
Если переменные описываются с ключевым словом Public, то они
доступны не только в рамках описания класса, но и извне, то есть
экземпляры других классов, их методы, могут непосредственно
обращаться к свойствам класса, описанным с областью видимости
Public и изменять (вводить новые, удалять старые, редактировать)
значения этих свойств.
Попробуем создать класс, свойства которого будут объявлены с
модификатором
(ключевым
словом)
Public
(публичный,
общедоступный). В проекте создадим объекты такого класса и
убедимся в том, что таким образом описанные свойства практически
не защищены от действий других объектов по их изменению.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Единственной защитой, которая сработает автоматически, является
проверка на соответствие типа назначаемого свойству значения, или
программист должен при использовании таких объектов сам
программировать степень доступа к свойствам объекта.
Создайте новый Windows-проект, в модуле класса проекта опишите
структуру класса Persona, инкапсулирующего два свойства – FullName
и PersonaId для хранения фамилии сотрудника (персоны) и его
персонального, например, табельного номера соответственно.
Public Class Persona
Public FullName As String
Public PersonaId As Integer
End Class
Даже такого скромного описания класса уже вполне достаточно, чтобы
иметь возможность создавать экземпляры класса Persona и
обращаться к свойствам этих экземпляров.
Dim Persona1 As New Persona
Можно присваивать новые значения свойствам объекта:
Persona1.FullName=”строка”
Persona1.PersonaId=число
или, наоборот:
“строка”=Persona1.FullName
Число=Persona1.PersonaId
На самом деле, даже пустое содержание класса, но обязательно
поименованного (имеющего имя), уже является классом.
Public Class Class1
End Class1
Экземпляры такого класса тоже могут быть созданы. Пока мы не
изучим механизм наследования классов, с объектами таких классов
мы работать не сможем, так как нам кажется, что класс не имеет ни
свойств, ни методов. Но следующая строчка кода не будет ошибкой
Dim cl1 as New Class1
В Windows-форме спроектируем интерфейс для тестирования
экземпляров созданного класса Persona. Примерный вид интерфейса
представлен на рис. 7.1. Форма имеет командную кнопку «Свойства
класса» для ввода информации об очередном клиенте, а также
командную кнопку «Тест» и текстовое поле для вывода информации о
сотруднике.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Рис. 7.1. Тестирование класса Persona
Создание экземпляра класса опишем в обработчике события –
нажатия кнопки «Свойства класса», а вывод информации в текстовое
поле – в обработчике события нажатия кнопки «Тест».
Dim Р As New Persona
’Создание экземпляра (объекта) класса Persona. P – это имя
создаваемого объекта; New – конструктор любого класса,
специальный метод, позволяющий создавать объекты класса. Вы
удивитесь, что никаких методов в классе Persona мы еще не
создавали, но любой класс автоматически имеет такой метод–
конструктор. Этот конструктор не требует входных параметров, то
есть он позволяет просто объявить объект обозначенного класса, не
инициируя его свойств, методов или событий.
В дальнейшем мы будем создавать собственные конструкторы наших
классов: с параметрами или без них.
Следует обратить внимание еще на одно обстоятельство: мы
объявили объект P с областью видимости Dim, но в описании кода на
уровне формы, другими словами, мы объявили объект с уровнем
видимости – текущая форма проекта.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
’ Используем обработчик события щелчка по командной кнопке
p.FullName = InputBox("Введите имя сотрудника")
‘Для организации диалога с пользователем используем стандартное
‘диалоговое окно InputBox, реализованное в виде функции,
‘возвращающей строковое значение
p.PersonaId = CInt(InputBox("Укажите его код"))
End Sub
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
В приведенном коде обработчика события «щелчок по командной
кнопке Button1» мы начали работу с созданным объектом: присвоили
свойству FullName значение, введенное пользователем в строку
стандартного диалогового окна InputBox. Аналогичным образом
происходит присвоение значения свойству объекта PersonaId, но так
как стандартная функция InputBox возвращает значение типа String, а
значение свойства PersonaId объявлено с типом Integer, требуется
явное преобразование типов. Преобразование типов значений удобно
выполнять с помощью стандартных функций, в нашем случае – CInt().
Обрабатывая нажатие другой командной, кнопки мы покажем в
текстовом окне (присвоим свойству Text объекта TextBox1)
информацию, созданную конкатенацией двух строк: p.FullName и
p.PersonaId. Обратите внимание на еще один способ согласования
типов переменных: у свойства объекта p.Personald, которое является
числом, был вызван метод ToString (этот метод достался нам по
наследству, но об этом узнаем позже).
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
‘В текстовое поле помещаем информацию, конкатенированную из
свойств экземпляра класса
TextBox1.Text = p.FullName & " - " & p.PersonaId.ToString
End Sub
Проект готов к работе. Можно вводить различные имена наших
персон, назначать им соответствующие персональные данные и
просматривать их в окне формы.
Конечно, в реальном приложении мы попытаемся сохранить всю
введенную информацию, например, в базе данных, с тем, чтобы
потом иметь к ней многократный доступ.
Предложенный способ хранения данных в классе предельно прост, но
имеет существенный недостаток, который заставляет описывать
свойства класса другим способом (задание 2). Недостаток
заключается в необходимости многократно повторять описание
всевозможных проверок допустимости вводимых значений в свойства
объектов.
Предположим, необходимо проверять, что введенная информация в
свойство FullName содержит только символы, но не цифры.
Реализуем проверку для ввода информации непосредственно в
интерфейсе проекта, для этого перепишем ввод данных в свойства
экземпляра класса.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim s As String
Dim ch As Char
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
s = InputBox("Введите имя сотрудника")
For Each ch In s
If Char.IsDigit(ch) Then
MsgBox("вводите только символы")
Exit sub
’Проверка недопустимости ввода цифровой информации. В случае
‘нарушения условия ввод прекращается
End if
Next
p.FullName = s
p.PersonaId = InputBox("Укажите его код")
End Sub
Проверка ввода допустимых символов выполнена следующим
образом:
 введена дополнительная переменная ch типа Char (символы,
2 байта таблицы UniCode);
 для перебора всех символов строки s организован цикл с
помощью конструкции For Each ch In s (строка представляет
собой набор символов);
 класс Char имеет общие (Shared) методы, которые позволяют
получить информацию о символе, мы воспользуемся методом
Char.IsDigit(ch), который возвращает True, если символ
является цифрой от 0 до 9;
 в случае, если метод Char.IsDigit(ch) вернет значение True
появляется сообщение о недопустимости введенного символа
и процедура ввода заканчивается.
Примечание:
С понятием «общий» или «shared метод» мы познакомимся позже, при
изучении методов класса. Такие методы, являясь общими для всего
класса, вызываются с именем класса, но не объекта класса. У класса
Char есть несколько таких методов, перечислим некоторые из них,
чтобы у вас была возможность потренироваться программировать
проверки допустимости значений свойств объектов.
Letter.IsDigit — возвращает True, если символ – цифра от 0 до 9;
Letter.IsNumber
—
возвращает
True,
если
символ
–
шестнадцатеричная цифра от 0 до F;
Letter.IsLetter — возвращает True, если символ – буква от A до Z;
Letter.IsLetterOrDigit — возвращает True, если символ – цифра от 0
до 9 или буква от A до Z;
Letter.IsLower и IsUpper — возвращает True в зависимости от
регистра символа;
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Letter.IsPunctuation
—
возвращает
True,
если
символ
классифицируется как знак пунктуации в таблице кодировки символов
UNICODE;
Letter.IsSymbol — возвращает True, если символ классифицируется
как символ в таблице кодировки символов UNICODE (symbol);
Letter.IsWhiteSpace
—
возвращает
True,
если
символ
классифицируется как символ пустого места в таблице кодировки
символов UNICODE.
Совершенно очевидно, что подобные проверки, если они необходимы,
должны быть также инкапсулированы в описании свойств в самом
классе. То есть, использование глобальных переменных (переменных
с областью видимости Public) для описания свойств класса допустимо
только в тех случаях, когда к свойствам класса можно обеспечить
доступ без соблюдения особых мер предосторожности.
Самостоятельно
Добавьте в проект проверку на допустимые символы при вводе
значения свойства P.PersonaId. Используйте для этого перечисленные
выше свойства класса Char. Протестируйте полученные результаты.
Задание 2. Описание свойств класса, как закрытых переменных
Задача
Обеспечить хранение свойств класса в закрытых переменных, доступ
к которым регламентирован.
Решение
При описании свойств класса использовать ключевое слово Private и
конструкцию Property.
Обсуждение
Применение ключевого слова Private перед именем переменной
гарантирует, что эта переменная, будет доступна только внутри
класса, то есть только собственные методы класса могут
непосредственно изменять значения таких свойств.
В этом случае для записи значения свойства в переменную и для
чтения этого значения используются процедуры свойств Property.
Доступ к значениям свойств класса внутри процедуры Property
осуществляется с помощью блоков Get и Set. Блок Get предназначен
для получения (считывания) значений свойств экземпляра класса, а
блок Set – для присваивания (установки или записи).
Интеллектуальный редактор Visual Studio.NET помогает описывать
свойства через конструкции Property. После того, как вы начнете
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
описывать заголовок конструкции Property с указанием имени
свойства, можно нажать клавишу ввода (Enter). Шаблон, который
появится на экране, будет выглядеть следующим образом:
Public Property ИмяСвойства()
Get
End Get
Set(ByVal Value)
End Set
End Property
Теперь осталось внести в этот шаблон описание доступа к
конкретному свойству класса, например, описание свойства FullName
класса Persona может выглядеть так:
Public Class Persona
Private _fullName As String
Private _personaId As Integer
Public Property FullName()
Get
‘Вернуть значение переменной
Return _fullName
End Get
Set(ByVal Value)
_fullName = Value
‘Присвоить значение переменной
End Set
End Property
Обратите внимание на имя переменной для хранения значения
свойства и на имя самого свойства. Лучше, если они будут похожи,
проще читается код класса. Обычно, названия свойств, объявленных
как Private описывают с тем же именем, что и названия самих свойств,
но добавляют префикс перед именем. Такой подход обеспечивает
внешнюю схожесть имен при их фактическом отличии.
Public Property PersonaID()
Get
Return _personaId
End Get
Set(ByVal Value)
Me._personaId = Value
End Set
End Property
End Class
Предлагаемый шаблон Property предельно формализован, его можно
подстроить под конкретные типы значений свойств.
Public Property FullName() as string
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Get
‘Вернуть значение переменной
Return _fullName
End Get
Set(ByVal Value as string)
_fullName = Value
‘Присвоить значение переменной
End Set
End Property
Public Property PersonaID() as integer
Get
Return _personaId
End Get
Set(ByVal Value as integer)
Me._personaId = Value
End Set
End Property
End Class
Конструкция Property является по синтаксису обычной функцией,
следовательно, можно добавить в ее сигнатуру типы возвращаемого
значения и входных параметров с учетом тех конкретных типов,
которые мы объявили при описании свойств класса.
Теперь рассмотрим создание экземпляров класса Persona и работу с
его свойствами.
Переменная _fullName используется только для хранения значений
свойства класса Person, а доступ к этим значениям выполняется с
помощью процедур Get (положить) и Set (взять). Для обращения к
свойству класса необходимо создать экземпляр класса и обратиться к
свойству класса:
Dim Person1 as New Persona
Person1.FullName=”Табуреткин Вася”
Экземпляр класса создается специальным методом New (конструктор
класса), создание и применение которого мы рассмотрим далее.
Теперь попробуем перенести проверку правильности ввода
информации в свойство FullName непосредственно в описание этого
свойства в рамках описания класса.
Public Class Persona
Private _fullName As String
Private _personaId As Integer
Public Property FullName() As String
Get
Return _fullName.ToUpper
End Get
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Set(ByVal Value As String)
Dim ch As Char
For Each ch In Value
If Char.IsDigit(ch) Then
MsgBox("вводите только символы")
Exit Property
End If
Next
Me._fullName = Value
End Set
End Property
Public Property PersonaID() as integer
Get
Return _personaId
End Get
Set(ByVal Value as integer)
Me._personaId = Value
End Set
End Property
End Class
Протестируйте класс, свойства которого описаны как закрытые
переменные.
Обратите внимание на строчку кода Return _fullName.ToUpper в блоке
Get описания свойства FullName. Конструкция Property используется
не только для обращения к переменной _fullname, она позволяет
выполнять любые программные действия, имеющие смысл, например,
изменять регистр при выводе значения свойства. Другими словами,
конструкцию
Property
необходимо
использовать
для
всей
необходимой обработки конкретного свойства класса.
Самостоятельно
Добавьте в описание свойства PersonaID ограничение на ввод чисел,
не находящихся в диапазоне от 0 до 100. Протестируйте написанный
код.
Задание 3. Использование конструкторов класса
Задача
Создавать экземпляры класса с помощью конструкторов класса,
которые позволят вводить начальные значения свойствам класса
(инициировать их).
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Решение
Описать в структуре класса специальные процедуры с именем New с
входными параметрами или без них.
Обсуждение
Для создания экземпляров класса в объектно-ориентированном
программировании используются специальные методы, называемые
конструкторами класса. Конструкторы по синтаксису является
процедурами.
Конструкторы класса используются для инициирования свойств
объекта класса. Конструктор может не описываться явно, в этом
случае среда CLR создает его по умолчанию. До сих пор, при
создании экземпляров класса мы использовали конструктор New,
который нам предоставляла среда CLR. Пришло время научиться
создавать собственные конструкторы.
Конструктор может иметь или не иметь входные параметры.
Конструкторов у класса может быть несколько (этот случай
полиморфизма будет рассмотрен далее в теме 8).
Приведем пример конструктора для экземпляров класса Persona.
Public Sub New(ByVal Name As String, ByVal pID As integer)
Me.FullName = Name
Ключевое слово Me служит для указания текущего класса
Me.PersonaID = pID
End Sub
Обратите
внимание
на
использование
ключевого
слова
(модификатора) Me. Это ключевое слово удобно применять для
указания на текущий объект.
Теперь при создании экземпляра класса следует вызывать
конструктор класса, который имеет параметры:
Dim Person1 as Persona = New Persona(“Петров”,567)
Самостоятельно
Добавьте в описание класса Persona свойство, позволяющее хранить
дату рождения сотрудника. Разработайте еще один конструктор
класса, при обращении к которому необходимо задать фамилию и
дату рождения сотрудника. Протестируйте добавленное свойство и
конструкторы класса.
Задание 4. Ограничение доступа к свойствам класса
Задача
Создать свойства класса, доступные только для чтения хранящихся в
них значений или только для записи.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Решение
При описании свойств класса использовать
(модификаторы) ReadOnly и WriteOnly.
ключевые
слова
Обсуждение
Добавив ключевое слово ReadOnly и удалив Set из блока Property, вы
можете определить свойство, которое доступно только для чтения.
Если вы добавите ключевое слово WriteOnly и удалите блок Get, вы
можете получить свойство, доступное только для записи.
Приведенный ниже код демонстрирует, каким образом можно создать
такие свойства на примере свойств Password и PersonId. Свойство
Password должно хранить пароль сотрудника, который можно только
записать, но нельзя прочитать. Свойство PersonaID хранит личный
номер сотрудника, который, наоборот, можно только просмотреть, но
нельзя изменить (назначение этого номера происходит при записи о
новом сотруднике однократно, редактированию не подлежит).
Опишем новое свойство Password по уже известной схеме с
применением конструкции Property.
Public Class Persona
Private _fullName As String
Private _personaID As Integer
Private _password As String
Public Property FullName() As String
Get
Return _fullName.ToUpper
End Get
Set(ByVal Value As String)
Dim ch As Char
For Each ch In Value
If Char.IsDigit(ch) Then
MsgBox("вводите только символы")
Exit Property
End If
Next
Me._fullName = Value
End Set
End Property
Public ReadOnly Property PersonaID() As Integer
Get
Return _personaID
End Get
End Property
Public WriteOnly Property Password() As String
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Set(ByVal Value As String)
_password = Value
End Set
End Property
End Class
Остается продумать: как будет записывать значение свойства
PersonaID. Обычно это делается в конструкторе класса, то есть при
создании объекта класса происходит присвоение значения свойствам,
имеющим атрибут ReadOnly. В дальнейшем эти значения могут быть
только прочитаны, но не изменены.
Необходимо внести изменения в описание конструктора класса, так
как теперь необходимо инициировать новое свойство Password и
продумать каким образом будет формироваться свойство PersonaId.
Предлагаем следующий вариант конструктора класса:
Public Sub New(ByVal Name As String, ByVal pass As String)
Dim randX As New Random
Создаем экземпляр класса случайных чисел (датчика случайных
чисел)
Me.FullName = Name
Ключевое слово Me служит для указания текущего класса
Me.Password = pass
_personaID = randX.Next(1, 100)
Вызываем метод Next датчика случайных чисел, который позволяет
получить число, находящееся в диапазоне от 1 до 100
End Sub
Закрытое для чтения свойство Password может использоваться
методами собственного класса, но недоступно для методов других
классов.
Самостоятельно
Протестируйте свойства Password и PersonaID. Убедитесь, что можно
только записать значение в свойство Password созданного объекта, но
при попытке чтения возникает ошибка.
При тестировании свойства PersonaID поработайте с датчиком
случайных чисел.
Класс Random генерирует псевдослучайные числа, то есть генерирует
числа, которые статистически случайны только при последовательном
просмотре. Работать с классом Random просто: нужно создать его
экземпляр и вызвать метод Next или метод NextDouble. Метод
NextDouble возвращает число с плавающей точкой и двойной
точностью в диапазоне от 0,0 до 1,0-(не включая). Метод Next
генерирует число, попадающее в указанный вами диапазон:
Dim rand As New Random
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Получение случайного дробного числа от 0,0 до 1,0
Dim randDouble As Double = rand.NextDouble
Получение случайного целого числа от 1 до 6
Dim randInt As Integer = rand.Next(1, 7)
Получение еще одного случайного целого числа от 1 до 6
randInt = rand.Next(1, 7)
Задание 5. Разделяемые переменные в классах
Задача
Создать переменную, которая будет общей, совместно используемой
всеми объектами данного класса.
Решение
Чтобы объявить переменную совместно используемой, необходимо
воспользоваться атрибутом (модификатором) Shared.
Обсуждение
Каждый создаваемый объект получает свою копию переменных,
объявленных в классе, – к примеру, каждый объект класса Persona
будет содержать свой набор переменных для свойств FullName,
PersonaId, Password. Однако иногда возникает потребность создать
переменную, которая будет общей, совместно используемой всеми
объектами данного класса.
Классический пример использования такой переменной – счетчик
количества созданных объектов класса. В принципе, в этом случае
можно воспользоваться глобальной переменной, но это будет
нарушением
логики
парадигмы
объектно-ориентированного
программирования: количество экземпляров – это свойство класса, а
не глобальное значение. К тому же, излишнее использование
глобальных переменных ведет к проблемам в связи с засорением
глобального пространства имен – все время придется придумывать
новые имена переменных, чтобы они не конфликтовали с уже
существующими именами.
Чтобы объявить переменную совместно используемой, необходимо
воспользоваться атрибутом (модификатором) Shared. Совместно
используемой переменной можно сразу присвоить начальное
значение при ее объявлении.
Добавим в класс Persona переменную для подсчета количества
созданных экземпляров и свойство, позволяющее пользователю
узнать текущее значение этого счетчика. Переменную объявим с
атрибутом (модификатором) Shared и присвоим ей начальное
значение 0.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Public Class Persona
Private _fullName As String
Private _personaID As Integer
Private _password As String
Private Shared Count As Integer = 0
Public Shared ReadOnly Property Counting() As Integer
Get
Return Count
End Get
End Property
Обратите внимание, что свойство Counting объявлено ReadOnly
(только для чтения), так как запись значений переменной будет
выполняться в конструкторах класса при создании очередного
экземпляра.
В каждый из имеющихся в структуре класса конструкторов класса
необходимо добавить строку:
Count += 1
Выполним это для нашего конструктора:
Public Sub New(ByVal fullName As String, ByVal password As String)
Dim randX As New Random
Me.FullName = fullName
Me.Password = password
_personaID = randX.Next(1, 100)
Count += 1
End Sub
В созданные вами конструкторы (задание 3) также добавьте
изменение значения свойства Count.
Осталось добавить в класс Persona метод Dispose(), который будет
изменять значений счетчика Count при удалении экземпляров класса
Persona.
Public Sub Dispose()
Count -= 1
End Sub
В конструкторы созданных вами классов также добавьте изменение
значения свойства Count.
Убедиться в работоспособности общего свойства Counting можно,
например,
следующим
вызовом
свойства:
MsgBox(Person.Counting.ToString) в любом месте текущего проекта.
Обратите внимание, что вызов свойства выполняется с именем
класса, но не объекта класса, так как переменная обслуживает весь
класс целиком, но не отдельные его экземпляры.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Самостоятельно
Протестируйте свойство Counting, создав несколько экземпляров
класса Persona. Примерный вид проекта для тестирования класса
Persona может выглядеть, например, как на рис. 7.2.
Проект включает командную кнопку и список ListBox для вывода
свойства FullName созданных экземпляров класса Persona.
Рис. 7.2. Пример формы для тестирования класса Persona
Если вы будете использовать интерфейс (рис. 7.2), то в этом случае
код тестирования может выглядеть следующим образом:
Dim x As New Persona("Petrov", "parol")
Dim y As New Persona("Sidorov")
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
ListBox1.Items.Add(x.FullName)
ListBox1.Items.Add(y.FullName)
MsgBox(Person.Counting)
End Sub
Задание 6. Синхронизация элементов управления
Задача
Создать браузер записей, автоматически выполняющий обновление
значений всех элементов управления в соответствии со значениями
свойств текущего объекта.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Решение
Создайте собственный класс для инкапсуляции данных, добавьте его
экземпляры в класс ArrayList и используйте механизм связывания с
данными, реализованный в .NET.
Обсуждение
Связывание с данными в .NET чаще всего применяется в
приложениях ADO.NET, которые должны отображать одну или более
записей из базы данных. Однако с той же легкостью его можно
использовать и в приложениях других типов, заменив базу данных
набором собственных объектов.
Допустим, вы хотите отображать в нескольких элементах управления
вашего проекта разные данные о сотрудниках. Для хранения данных о
сотрудниках используем разработанный ранее класс Persona. Для
хранения нескольких экземпляров Persona можно использовать
динамический класс System.Collections.ArrayList.
Класс ArrayList обычно используется для работы с массивами данных.
Для добавления элементов в него служит метод Add, а для удаления
– методы Remove, RemoveAt и RemoveRange (очень похоже на
элемент управления ListBox, который вы могли использовать в
задании 5).
Dim Persons As New ArrayList
Dim newPerson As New Persona("Дятлов", "D123")
Persons.Add(newPerson)
newPerson = New Persona("Сорокин", "S654")
Persons.Add(newPerson)
newPerson = New Persona("Рыжиков", "R875")
Persons.Add(newPerson)
newPerson = New Persona("Груздев", "G089")
Persons.Add(newPerson)
newPerson = New Persona("Волнушкин", "V456")
Persons.Add(newPerson)
Наконец, вы можете связать несколько элементов управления,
размещенных в форме, с одним объектом ArrayList. Для связи
элемента управления – списка нужно просто установить его свойство
DataSource так, чтобы оно ссылалось на наш объект ArrayList. Кроме
того, свойству DisplayMember списка следует присвоить имя свойства
связанного объекта, которое требуется отображать.
ListBox1.DataSource = Persons
ListBox1.DisplayMember = "FullName"
Многие другие элементы управления .NET, такие как кнопки,
текстовые поля и надписи, не предоставляют особых возможностей
связывания с данными, но они поддерживают связывание с данными
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
через набор DataBindings. Набор DataBindings позволяет связать
любое свойство элемента управления со свойством собственного
класса.
Так вы можете связать свойство Text текстового поля со свойством
Persona.FullName. После этого значение из объекта Persona будет
автоматически выводиться в текстовое поле, а изменения текстового
поля будут автоматически отражаться в объекте Persona.
Следующий код выполняет связывание двух текстовых полей и
свойств объектов класса Persona.
TextBox1.DataBindings.Add("text", Persons, "FullName")
TextBox2.DataBindings.Add("text", Persons, "PersonaId")
Итоговая форма проекта показана на рис. 7.3. Элементы управления
ListBox1, TextBox1 и TextBox2 синхронизированы. Таким образом,
выбор в списке любого объекта приводит в выводу значений свойств
этого же объекта и в текстовых полях.
Рис. 7.3. Синхронизированные элементы управления для просмотра нескольких
экземпляров класса Persona
Самостоятельно
Добавьте в форму разработанного проекта элемент управления для
вывода даты рождения сотрудника. Синхронизируйте просмотр
свойств у различных объектов.
Задание 7. Создание класса Vector (свойства класса)
Задача
Выполнение действий над трехмерными векторами.
Решение
Создайте собственный класс вектора.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Обсуждение
.NET Framework не поддерживает операции с векторами. Необходимо
разработать пользовательский класс Vector. Предположительно
структура класса может быть следующей:
Public Class Vector
'Координаты вектора
Private x, y, z As Double
‘При описании свойств с помощью конструкций Property необходимо
осуществлять проверку на допустимость вводимой информации в
переменные x, y, z
'Конструктор класса
Public sub New()
End Sub
Методы класса Vector будут рассмотрены в следующей теме
'Сложение вектора с имеющимся вектором
Public function Add()
End Function
End Class
Самостоятельно
Разработайте интерфейс для тестирования класса Vector. Добавьте в
описание класса Vector разделяемую переменную для подсчета числа
созданных экземпляров класса.
Задание 8. Работа с простыми дробями
Задача
Выполнение
математических
действий
над
дробями
без
преобразования их в десятичную форму (которое может приводить к
ошибкам округления).
Решение
Разработайте собственный класс простой дроби.
Обсуждение
.NET Framework не поддерживает действий над простыми дробями.
Однако создать такой класс совсем несложно. Этот класс будет
включать методы Add, Subtract, Multiply и DivideBy, которые будут
запрограммированы при изучении следующей темы. В этом задании
необходимо описать свойства класса и конструкторы класса.
Предложения по именованию свойств класса следующие:
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Public Class Fractal
'Два компонента любой простой дроби
Private Denominator As Integer
Private Numerator As Integer
‘При описании свойств с помощью конструкций Property необходимо
осуществлять проверку на допустимость вводимой информации в
переменные Denominator, Numerator.
Обратите внимание на тот факт, что знаменатель дроби должен быть
отличен от нуля.
'Создание новой дроби
Public sub New()
End Sub
Методы класса
End Class
Самостоятельно
Разработайте интерфейс для тестирования класса Fractal. Добавьте в
описание класса Fractal разделяемую переменную для подсчета числа
созданных экземпляров класса.
Задание 9. Печатающаяся строка
Задача
Получить
анимационный
эффект
печатающейся
строки
регулируемыми параметрами (содержание и скорость печати).
с
Решение
Разработайте собственный класс, например Words, который
позволяет хранить любую строку текста и изменять скорость ее
вывода в любом элементе управления формы.
Обсуждение
Прежде, чем создавать класс Words, необходимо обсудить, как
работает элемент управления Timer. Таймеры используются для
решения двух основных задач – измерения отрезков времени и
синхронизации процессов с часами операционной системы. Таймеры
– не визуальные элементы управления: при работе программы они не
отображаются на форме.
Таймеры имеют лишь два свойства – Enabled и Interval, а также
поддерживают только одно событие Tick. Применительно к таймеру,
значение свойства Enabled означает, таймер запущен (Enabled=True)
или таймер остановлен (Enabled=False).
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Суть работы таймера сводится к тому, что он генерирует событие Tick
каждые Interval миллисекунд.
Перейдем к решению нашей задачи. Требуется организовать
движение некоторой надписи с определенной скоростью. Такое
движение можно организовать с применением таймера, у которого
можно регулировать свойство Interval. То есть, при создании класса
Words мы должны инкапсулировать в нем как минимум два свойства:
одно – для хранения самой строки, другое – для хранения скорости ее
вывода. Класс Words мог бы выглядеть, примерно, так:
Public Class Words
Public msg As String
Public interval As Integer
Public Sub New(ByVal message As String, ByVal interval As Integer)
Me.msg = message
Me.interval = interval
End Sub
End Class
Спроектируем форму для исследования поведения экземпляров
класса и возможностей элемента Timer (рис. 7.4). Обратите внимание,
что элемент управления Timer1 – это не визуальный элемент, при
конструировании формы этот элемент перетаскивается в нижнюю
часть формы, но при запуске проекта элемент не будет виден.
Добавим в форму код обработки командных кнопок и таймера.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Dim MyMessage As New Words("Изучайте языки программирования,
это очень обогащает Ваш словарный запас", 200)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
If Button1.Text = "Старт" Then
Timer1.Enabled = True
Timer1.Interval = MyMessage.interval
Button1.Text = "Стоп"
Else
Timer1.Enabled = False
Button1.Text = "Старт"
End If
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Timer1.Tick
' Анимация слева направо
Static c As Integer = 0
Label1.Text = MyMessage.msg.Substring(0, c)
Me.Text = MyMessage.msg.Substring(0, c)
c += 1
If c = MyMessage.msg.Length() + 1 Then c = 0
'Анимация справа налево
Dim title2 As String = "Кнопка"
Static i As Integer = title2.Length()
Button2.Text = title2.Substring(0, i)
i -= 1
If i = -1 Then i = title2.Length()
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
MsgBox("У нас все получится", "Программируйте, и все будет
хорошо!")
End Sub
Не забудьте присвоить свойству text кнопки Button1 – значение
«Старт», так как это значение используются в коде программы.
Разберем, что мы написали. Кнопка с надписью Старт запускает
таймер, при этом надпись Старт меняется на Стоп. При повторном
нажатии надпись Стоп заменяется обратно на Старт. При этом
происходит включение и выключение таймера (рис. 7.4). Вся работа
по созданию эффекта происходит в событии таймера Tick. Далее идет
использование объекта класса Words,. свойства которого мы
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
используем для организации выводимой в Label1 строки и для
указания частоты обращения к таймеру.
Рис. 7.4. Проект «Бегущая строка» в действии
Самостоятельно
Измените процесс вывода текста: пусть он не наращивается, а
наоборот, уменьшается. В этом случае вам придется использовать
еще один счетчик I, начальное значение которого пусть будет равным
длине строки, а при каждом срабатывании таймера вычитайте один
символ из строки. При достижении счетчиком значения 0 снова
присвойте ему старое значение длины строки.
Примените написанный код не к Label, а ко второй кнопке.
Download