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

advertisement
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
1
Практическая работа по теме 8. Модели решения
функциональных и вычислительных задач
Конструкторы и деструкторы классов. Методы как интерфейс
класса. Сигнатура методов: процедуры и функции. Перегрузка
методов и конструкторов класса – разновидность полиморфизма.
Наследование классов. Базовый класс, его конструкторы, свойства,
методы. Ключевые слова MyBase, MyClass, Me. Полиморфизм.
Переопределенные методы. Абстрактные классы, их назначение и
устройство. Применение модификаторов доступа в базовых
классах: Public, Private, Protected. Использование затенения
(shadowing) методов базового класса.
Практическая работа по теме 8. Модели решения функциональных и вычислительных
задач ................................................................................................................................................1
Задание 1. Разработка конструкторов и деструкторов класса ..............................................1
Задание 2. Методы как интерфейс класса ...............................................................................4
Задание 3. Перегрузка методов и конструкторов класса – разновидность полиморфизма6
Задание 4. Создание класса Vector (методов класса) .............................................................9
Задание 5. Работа с простыми дробями.................................................................................12
Задание 6. Наследование конструкторов, свойств и методов базового класса .................14
Задание 7. Полиморфизм. Переопределенные методы ........................................................18
Задание 8. Практическое использование иерархии классов ...............................................20
Задание 9. Абстрактные классы .............................................................................................21
Задание 10. Абстрактные классы в стандартных библиотеках ...........................................22
Задание 11. Применение модификаторов доступа в базовых классах ...............................26
Задание 12. Затенение свойств и методов базового класса .................................................27
Задание 13. Иерархия классов «Фигуры» .............................................................................29
Задание 1. Разработка конструкторов и деструкторов класса
Задача
Управлять процессом создания и удаления объектов класса с
помощью методов класса.
Решение
Разработать собственные методы класса New()
позволяющие создавать или удалять объекты класса.
и
Dispose(),
Обсуждение
Поскольку создание и использование конструкторов класса было
рассмотрено в теме 2 (без описания конструкторов невозможно было
бы выполнить тестирование свойств класса), сейчас мы остановимся
на более тонких моментах в применении конструкторов – на области
видимости конструктора класса.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
2
Это очень важный момент, так как возможность создания экземпляров
класса зависит от области видимости конструкторов этого класса.
Ограничивая область видимости конструкторов ключевыми словами
(модификаторами) Private или Friend, можно запретить создание
объектов за пределами сборки.
Конструкторы класса могут быть закрытыми, то есть объявленными с
ключевым словом Private и доступными только собственным методам
и свойствам класса. Для чего нужен закрытый конструктор, который
может вызываться только в пределах класса? Ведь экземпляры
класса внутри самого класса обычно не создаются?
Закрытые конструкторы полезны в тех случаях, когда объект класса
должен создавать дополнительные экземпляры своего класса или
если вы хотите, чтобы создание объекта класса выполнялось не
обычным стандартным образом (оператором New), а другим, менее
привычным образом.
В качестве альтернативного способа создания экземпляра класса
можно использовать Shared-методом класса. Shared-метод, как и
Shared-свойство, является общим методом класса, решает общие для
всего класса задачи. В отличие от Shared-свойства, которое
вызывается только с именем класса, Shared-метод может вызывается
с именем экземпляра класса.
Ниже
приведен
пример
описания
закрытого
конструктора,
использование Shared-метода для создания экземпляра класса и
тестирование применения такого подхода.
Public Class Class1
Public name As String
Private Sub New()
name = "Default"
End Sub
Public Sub New(ByVal NewName As String)
name = NewName
End Sub
Public Shared Function DefaultObject() As Class1
Return New Class1
End Function
End Class
Класс Class1 имеет два конструктора, один из которых является
закрытым конструктором, так как объявлен с областью видимости
Private. Это конструктор создает экземпляр класса в режиме «поумолчанию», то есть с какими-то постоянными значениями свойств.
Как обратиться к закрытому конструктору?
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
3
Dim c As New Class1("First")
Создать объект при помощи закрытого конструктора невозможно. К
закрытому конструктору можно обратиться только при помощи
открытого метода.
Dim c1 = c.DefaultObject()
Label1.Text = c.name
Label2.Text = c1.name
End Sub
На рис. 1. видно, что оба экземпляра класса были успешно созданы.
Рис. 1. Тестирование конструкторов класса
Самостоятельно
Добавьте в описание Class1 Shared-свойство для подсчета количества
созданных экземпляров и протестируйте его. Пример создания и
использования Shared-свойств рассмотрен в задании 5 темы 2.
Теперь рассмотрим как в .NET происходит удаление объектов.
Компания Microsoft встроила в CLR автоматическую систему
управления памятью в виде системного класса Garbage Collector,
который называют «сборщиком мусора». При создании объекта CLR
выделяет для него память, а «сборщик мусора» периодически
проверяет память в поисках объектов, которые больше не
используются (на которые отсутствуют ссылки), и удаляет их. Другими
словами, удаление ненужных объектов выполняется автоматически.
Применение класса Garbage Collector, конечно же, предоставляет
разработчика .NET определенные удобства, но, с другой стороны, они
при этом лишаются возможности контролировать процесс удаления
объектов из памяти.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
4
Для того чтобы обойти эти проблемы, компания Microsoft рекомендует
применять следующую технологию: если вам нужно управлять
процессом создания объектов и удалением их из памяти, создавайте
собственный метод (деструктор), который будет вызываться после
последнего обращения к объекту. Код, приведенный ниже, выполняет
пользовательский метод Dispose(), освобождающий ресурсы.
Public Sub Dispose()
Me.value = Nothing
Counter -= 1
Если была объявлена переменная типа Shared
End Sub
Самостоятельно
Добавьте в описание класса Class1 деструктор класса (метод,
удаляющий объекты класса из оперативной памяти) и напишите
программный код для тестирования деструктора.
Задание 2. Методы как интерфейс класса
Задача
Разработать интерфейс класса.
Решение
Использовать процедуры и функции для реализации поведения
объектов класса.
Обсуждение
Требуемое поведение объектов класса обеспечивается не только при
помощи свойств, но и при помощи методов.
Метод – это функция или процедура, определенная как часть
реализации класса. Как и свойства, методы класса могут быть
открытыми или закрытыми. Открытые методы составляют интерфейс
класса, а закрытые используются для внутренних нужд класса.
Воспользуемся классом Persona, разработку которого мы начинали в
заданиях к теме 7. Добавим в описание класса методы Login и
ToShow.
Метод Login, реализованный в виде функции, позволяет получить
пароль пользователя, собранный из его имени и личного
идентификатора. Рассмотрим пример функции, назначающей Login
для класса Persona:
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
5
Public Function Login(ByVal fullname As String) As String
Return Me.FullName & Me.PersonaID.ToString
End Function
Другой пример методов – функция ToShow(), позволяющая выполнять
обычный текстовый вывод свойства FullName с изменением регистра
строки:
Public Function ToShow() As String
Return FullName.ToUpper
End Function
Самостоятельно
Добавьте в описание класса Persona свойство, позволяющее хранить
изображение (фото сотрудника). Самостоятельно разработайте
метод, позволяющий выводить это изображение в любой элемент
управления, поддерживающий графику, например, в PictureBox или
непосредственно на форму.
Пример использования графического вывода приведен на рис. 2.
Рис. 2. Пример использования методов графического вывода
Мы с вами уже знакомы с графическими свойствами объектов, но в
качестве подсказки можно рассмотреть варианты написания метода
вывода графики в элемент управления.
В классе Persona вы добавляете описание свойства и метода.
Public Class Persona
Private _fullName As String
Private _personaID As Integer
Private _password As String
Private Shared count As Integer = 0
Public foto As Image
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
6
Public Sub ShowFoto(ByVal s As String)
Me.foto = Image.FromFile(s)
End Sub
В проект добавляете форму, состоящую, например, из текстового окна
и графического окна Picturebox (как на рис. 2). К процедуре загрузки
формы можно написать следующий код:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim p As New Persona("Макдональд Мэтью", "ММ")
TextBox1.Text = p.FullName
p.ShowFoto("L:\VB.NET\big_me2.jpg")
PictureBox1.Image = p.foto
End Sub
Имя файла, содержащего изображение, должно соответствовать
вашему проекту.
В этом варианте мы использовали стандартный класс Image и его
Shared метод Image.FromFile, позволяющий получить графическое
изображение из файла, имя которого передано в метод в качестве
входного параметра.
Далее, мы это изображение присваиваем нашему свойству foto,
объявленному с типом image.
Задание 3. Перегрузка методов и конструкторов класса –
разновидность полиморфизма
Задача
Определить не один, а несколько методов, имеющих одно и тоже имя,
но выполняющих разные задачи.
Решение
Использовать механизм перегрузки методов (полиморфизм).
Обсуждение
Перегрузка методов (один из случаев полиморфизма) в классе
осуществляется путем определения нескольких методов, имеющих
одинаковые имена, но различные сигнатуры.
Сигнатура метода – это комбинация имени метода и списка его
формальных параметров. Если вы внесете изменения в список
параметров метода (типы параметров, их количество), то создадите
новую сигнатуру метода, то есть другой метод, но с тем же именем.
При обращении к методу вы задаете список фактических параметров.
Компилятор, после анализа всех имеющихся для метода с таким
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
7
именем списков параметров, определит, какой именно метод из
списка одноименных необходимо вызвать для вас.
В каких случаях и для чего используют полиморфизм? При описании
классов довольно часто используют перегрузку для создания
нескольких вариантов конструктора класса New(), что позволяет поразному инициировать экземпляры класса. Полиморфизм используют
и при программировании других методов класса, так как одинаковые
по смыслу действия (имеющие отличия) удобнее именовать
одинаково.
В сигнатуре перегружаемого метода следует указать модификатор
Overloads. Рассмотрим пример нашего класса Persona.
Public Overloads Sub ShowFoto(ByVal s As String)
End Sub
Public Overloads Sub ShowFoto(ByVal obj As Object, ByVal s As String)
End Sub
Ключевое слово (модификатор) Overloads является необязательным
в случае, если перегружаемые методы принадлежат одному классу, в
этом случае модификатор можно не использовать.
Public Sub ShowFoto(ByVal s As String)
Me.foto = Image.FromFile(s)
End Sub
Public Sub ShowFoto(ByVal obj As Object, ByVal s As String)
End Sub
Рассмотрим случай перегрузки методов класса на примере перегрузки
конструктора класса. Предположим, что при создании некоторых
экземпляров класса Persona необходимо инициировать все свойства
класса (фамилию и пароль), а при создании других экземпляров
класса – только одно из свойств (фамилию), ввод пароля будет
отложен. В этом случае описание конструкторов класса Persona будет
выглядеть следующим образом:
Public Class Persona
Private _fullName As String
Private _personID As Integer
Private _password As String
Public Sub New(ByVal fullName As String, ByVal password As String)
Dim randX As New Random
Me.FullName = fullName
Me.Password = password
_personID = randX.Next(1, 100)
End Sub
Public Sub New(ByVal fullName As String)
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
8
Dim randX As New Random
Me.FullName = fullName
_personID = randX.Next(1, 100)
End Sub
End Class
Перегрузка методов класса является разновидностью полиморфизма
(многовариантности, многоформенности), так как предполагает
различия в списке параметров одноименных методов. Перегрузка
является частным проявлением полиморфизма, полиморфизм в
общем виде и такого различия не требует.
Самостоятельно
Добавьте в класс Persona еще один перегруженный метод ToShow,
позволяющий выполнять графический вывод свойства FullName на
любую поверхность, поддерживающую графическое изображение. На
рис. 3 одновременно используются оба перегруженных метода вывода
свойства FullName: текстовый и графический.
Рис. 3. Использование перегруженных методов текстового и графического вывода
свойства FullName
В качестве одного из вариантов создания перегруженных методов
можно рассмотреть следующий пример.
Функция ToShow() для текстового вывода свойства FullName может
быть организована, например, так:
Public Function ToShow() As String
Return FullName.ToUpper
End Function
Перегруженный метод ToShow() для графического вывода свойства
FullName может рисовать объемный текст.
Public Sub ToShow(ByVal obj As Object)
Dim sb As New SolidBrush(Color.Gray)
Dim f As New Font("Tahoma", 18, FontStyle.Bold)
Dim g As Graphics = obj.creategraphics
g.DrawString(Me.FullName, f, sb, 10, 10)
sb.Color = Color.White
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
9
g.DrawString(Me.FullName, f, sb, 8, 8)
sb.Dispose()
f.Dispose()
g.Dispose()
End Sub
Для организации графического вывода можно придумать что-нибудь
оригинальное, например, выпуклый текст. Достигаются подобные
эффекты, как вы могли увидеть, простым смещением текста с другим
цветом, имитирующим тень.
В проекте поместим кнопку и в качестве обработчика события щелчка
по кнопке напишем следующий код:
Dim p As New Persona("Макдональд Мэтью", "ММ")
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
TextBox1.Text = p.ToShow
p.ToShow(PictureBox1)
End Sub
Задание 4. Создание класса Vector (методов класса)
Задача
Выполнение действий над трехмерными векторами.
Решение
Создайте собственный класс вектора.
Обсуждение
.NET Framework не поддерживает операции с векторами. Необходимо
создать класс Vector, включающий методы Add, Subtract, Multiply и
DivideBy. Предположительно структура класса может быть
следующей:
Public Class Vector
'Координаты вектора
Private x, y, z As Double
'Конструктор класса
Public sub New()
End Sub
'Сложение вектора с имеющимся вектором
Public function Add()
End Function
'Вычитание вектора из имеющегося вектора
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
10
Public function Subtract()
End Function
'Умножение имеющегося вектора на скаляр
Public function Multiply()
End Function
'Умножение имеющегося вектора на вектор
‘Обратите внимание – можно создать перегруженный метод
Public function Multiply()
End Function
'Деление имеющегося вектора на скаляр
Public function DivideBy()
End Function
'Определение длины вектора
Public function Length()
End Function
Метод для графического вывода вектора
Public Sub ToShow()
End Sub
End Class
Разработайте интерфейс для тестирования класса Vector. Добавьте в
описание класса Vector разделяемую переменную для подсчета числа
созданных
экземпляров
класса.
Пример
интерфейса
для
тестирования класса Vector представлен на рис. 4.
Рис. 4. Пример интерфейса для тестирования класса Vector
Примечание
При разработке программного кода используйте следующие формулы
для Декартовой системы координат:
1. Покоординатное сложение векторов a и b
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
11
 a x  b x   a x  b x 
a   b   a  b 
y
 y  y  y
 a z  bz   a z  bz 
2. Скалярное произведение векторов
a•b=a x b x + a y b y + a z b z
3. Векторное произведение векторов
a x b=(a y b z -a z b y )i+(a z b x -a x b z )j+(a x b y -a y b x )k
4. Длина вектора
l  ax2  a y2  az2
5. Прежде чем приступать к рисованию вектора в любом элементе
управления, например, в PictureBox, можно выполнить некоторую
подготовку, например, перенести отсчет координат в центр
PictureBox (см. текст процедуры MapGraphicsWindow) и провести
координатную сетку (процедура DrawAxes). Так будет гораздо
удобнее, чем отталкиваться от верхней левой точки элемента
управления.
‘Процедура преобразования глобальных координат устройства в
требуемые вам координаты
Public Sub MapGraphicsWindow(ByVal g As Graphics, _
ByVal wxmin As Single, ByVal wymin As Single, _
ByVal wxmax As Single, ByVal wymax As Single, _
ByVal dxmin As Single, ByVal dymin As Single, _
ByVal dxmax As Single, ByVal dymax As Single)
' Преобразуем глобальные координаты центра
g.TranslateTransform(-(wxmax + wxmin) / 2, _
-(wymax + wymin) / 2, MatrixOrder.Append)
' Масшабируем
Dim sx As Single
sx = CSng((dxmax - dxmin) / (wxmax - wxmin))
Dim sy As Single
sy = CSng((dymax - dymin) / (wymax - wymin))
g.ScaleTransform(sx, sy, MatrixOrder.Append)
' Преобразуем в центр формы
g.TranslateTransform((dxmax + dxmin) / 2, _
(dymax + dymin) / 2, MatrixOrder.Append)
End Sub
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
12
Private Sub DrawAxes(ByVal g As Graphics)
' Рисуем координатные оси
Dim x As Double
Dim y As Double
'Черное перо для координатных осей
Dim p_axes As New Pen(Color.Black, 0)
g.DrawLine(p_axes, -2, 0, 2, 0)
' Шкала по оси X
For x = -2 To 2 Step 0.5
g.DrawLine(p_axes, CSng(x), CSng(-0.1), CSng(x), CSng(0.1))
Next x
' Шкала по оси Y
g.DrawLine(p_axes, 0, -2, 0, 2)
For y = -2 To 2 Step 0.5
g.DrawLine(p_axes,CSng(-0.1),CSng(y),CSng(0.1),CSng(y))
Next y
End Sub
Задание 5. Работа с простыми дробями
Задача
Выполнение
математических
действий
над
дробями
без
преобразования их в десятичную форму (которое может приводить к
ошибкам округления).
Решение
Разработайте собственный класс простой дроби.
Обсуждение
.NET Framework не поддерживает действий над простыми дробями.
Однако создать такой класс совсем несложно. Этот класс будет
включать методы Add, Subtract, Multiply и DivideBy. Предложения по
именованию свойств и методов класса следующие:
Public Class Fraction
'Два компонента любой простой дроби
Private Denominator As Integer
Private Numerator As Integer
'Создание новой дроби
Public sub New()
End Sub
Методы класса
Сложение дроби с имеющейся дробью
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
13
Public Function Add()
End Function
Вычитание дроби из имеющейся дроби
Public Function Subtract()
End Function
Умножение имеющейся дроби на указанную дробь
Public Function Multiply()
End Function
Деление имеющейся дроби на указанную дробь
Public Function DivideBy()
End Function
End Class
Разработайте интерфейс для тестирования класса Fraction. Пример
интерфейса для тестирования класса Fraction представлен на рис. 5.
Рис. 5. Пример интерфейса для тестирования класса Fraction
Обратите внимание на результат запрограммированных действий (в
данном случае на рис. 5 выполнено сложение простых дробей).
Результат представлен без сокращения дроби и учета ее знака. Все
необходимые корректировки внесем позже, при освоении темы,
связанной со стандартными интерфейсами.
В качестве помощи рассмотрим фрагмент кода описания класса
Fraction, создания и применения экземпляров этого класса.
Public Class Fraction
Public Denominator As Integer
Public Numerator As Integer
Public Sub New(ByVal numerator As Integer, ByVal denominator As
Integer)
Me.Numerator = numerator
Me.Denominator = denominator
End Sub
Public Function Add(ByVal fraction As Fraction) As Fraction
Return New Fraction(Me.Numerator * fraction.Denominator +
fraction.Numerator * Me.Denominator, Me.Denominator *
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
14
fraction.Denominator)
End Function
Public Function Subtract(ByVal fraction As Fraction) As Fraction
Return New Fraction(Me.Numerator * fraction.Denominator fraction.Numerator * Me.Denominator, Me.Denominator *
fraction.Denominator)
End Function
End Class
Рассмотрим применение класса в проекте. Кнопка Button1
предназначена для выполнения сложения дробей, кнопка Button2 –
вычитания.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim fraction1 As New Fraction(CInt(TextBox1.Text), CInt(TextBox4.Text))
Dim fraction2 As New Fraction(CInt(TextBox2.Text), CInt(TextBox5.Text))
fraction1 = fraction1.Add(fraction2)
TextBox3.Text = fraction1.Numerator
TextBox6.Text = fraction1.Denominator
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Dim fraction1 As New Fraction(CInt(TextBox1.Text), CInt(TextBox4.Text))
Dim fraction2 As New Fraction(CInt(TextBox2.Text), CInt(TextBox5.Text))
fraction1 = fraction1.Subtract(fraction2)
TextBox3.Text = fraction1.Numerator
TextBox6.Text = fraction1.Denominator
End Sub
Задание 6. Наследование конструкторов, свойств и методов
базового класса
Задача
Создавать и использовать в проектах иерархию классов.
Решение
Создать базовый (родительский) и дочерние классы, связанные
механизмом наследования.
Обсуждение
Одним из наиболее мощных свойств объектно-ориентированных
языков является наследование – возможность создавать класс со
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
15
свойствами и методами, которые могут быть использованы в других
классах. В терминологии ООП базовый класс называется
наследуемым (родительским), а производные от него –
наследниками (дочерними).
Цель наследования заключается в создании базового класса, в
котором инкапсулируются свойства и методы, необходимые
множеству производных классов того же типа. На основе базового
класса создаются другие классы, которые, как правило, не ограничены
свойствами и методами этого класса, а имеют более широкие
возможности.
При описании классов-наследников, необходимо показать какой класс
для них является базовым, это делается с помощью ключевого слова
Inherits.
Public Class A
End class A
Public Class B
Inherits A
End Class B
Если следует запретить наследование свойств и методов класса
(закрытый класс), то в его описании необходимо добавить ключевое
слово NotInheritable.
Public NotInheritable Class A
Каждый класс может иметь только один базовый (родительский)
класс, но сам может являться базовым классом для многих классов. В
VB.NET запрещено множественное наследование, но имеется
механизм интерфейсов – аналог множественного наследования,
который мы изучим позже.
В качестве примера рассмотрим иерархию
наследования,
построенную для классов Number (базовый класс) и двух его
наследников RomanNumber (римские цифры) и ArabianNumber
(арабские цифры). Иерархия классов изображена на рис. 6.
Модель классов построена в редакторе PowerDesigner, который
представляет собой профессиональную среду для создания диаграмм
классов. Обратите внимание на графическое изображение свойств,
объявленных как Public или Private (значки + и -), описание типов
данных, и присвоение им начальных значений. Наследование на
диаграмме изображается пустой стрелкой, обращенной к базовому
классу.
Создайте Windows проект, включающий три модуля классов: Number,
RomanNumber и ArabianNumber, а также форму с элементами
управления для тестирования поведения классов.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
16
Number
+ Value
: UInt16
- Counter : UInt16
+
+
+
+
=0
New ()
Dispose ()
Instances ()
: UInt16
ShowNumber () : String
RomanNumber
ArabianNumber
+ New ()
+ New ()
Рис. 6. Иерархия классов
В соответствии и диаграммой классов (рис. 6) опишем иерархию
классов программным образом. Класс Number имеет свойство Value,
которое описывает значение (число); свойство Value доступно извне,
поэтому объявлено с ключевым словом Public:
Public Class Number
Public Value As Integer
Private Shared Counter As Integer = 0
Public Sub New()
Value = 0
Counter += 1
End Sub
Public Sub New(byval n as integer)
Value = n
Counter += 1
End Sub
Public Sub Dispose()
Counter -= 1
End Sub
Public Shared ReadOnly Property Instances() As Integer
Get
Return Counter
End Get
End Property
Public Function ShowNumber() As String
Return Me.value.ToString
End Function
End Class
В классе объявлен метод ShowNumber, который выводит на экран
число, cодержащееся в свойстве Value класса Number, в текстовом
формате.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
17
Создадим два класса наследника: RomanNumber и ArabianNumber,
которые пока будут только наследовать свойства и методы класса
Number.
Public Class RomanNumber
Inherits Number
Public Sub New(ByVal n As Integer)
MyBase.New(n)
End Sub
End Class
Public Class ArabianNumber
Inherits Number
Public Sub New(ByVal n As Integer)
MyBase.New(n)
End Sub
End Class
Все классы создаются в отдельных модулях, не смотря на то, что они
представляют единую иерархию.
Уделим должное внимание конструкторам классов наследников. Так
как базовый класс Number имеет конструктор New() с параметрами, то
в конструкторах классов наследников первой строкой кода должна
быть: MyBase.New(параметры).
Ключевое слово MyBase позволяет вызвать конструктор базового
класса с целью инициализации в классе наследнике той части кода,
которую он наследует от базового класса. Далее, в конструкторе
производного класса могут инициироваться собственные свойства,
если они есть (в нашем случае, пока ничего нет). При обращении к
собственным свойствам следует указывать другое ключевое слово
(модификатор) — Me.
Уже в таком скромном представлении классы RomanNumber и
ArabianNumber могут быть протестированы, так как они, так же, как и
класс Number, могут содержать число и выводить его в виде текста.
Пока все три класса устроены одинаково – изображение числа в
разных классах не отличается. Пример тестирования иерархии
классов приведен ниже (рис. 7).
Самостоятельно
Код для тестирования классов напишите самостоятельно.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
18
Рис. 7. Тестирование иерархии классов
Задание 7. Полиморфизм. Переопределенные методы
Задача
Изменять поведение дочерних классов по отношению к поведению
базового класса.
Решение
Использовать полиморфизм – создавать одноименные методы,
выполняющие разные действия.
Обсуждение
Важной
особенностью
объектно-ориентированного
программирования, связанной с иерархией классов, является
возможность послать одинаковые сообщения сразу нескольким
объектам различных классов. Объектам предоставляется право
выбрать, кто из них будет это сообщение обрабатывать. Другими
словами, полиморфизм – это способность объектов, принадлежащих
разным классам, реагировать на один и тот же вызов метода с
помощью собственной реализации метода.
Такие методы называются переопределенными, у классов
наследником они помечаются ключевым словом (модификатором)
Overrides, а у класса родителя – модификатором Overridable.
Например,
Public Overridable Function ShowNumber() As String
Так
будет
выглядеть
описание
метода,
подлежащего
переопределению, у родительского класса,
Public Overrides Function ShowNumber() As String
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
19
А так будет выглядеть сигнатура переопределенного метода у класса
наследника.
Обратите внимание на полное совпадение сигнатур методов, при
перегрузке методов сигнатуры должны быть различными, а при
переопределении – сигнатуры могут совпадать.
Теперь вернемся к нашему примеру с числами и попробуем
переопределить метод вывода числа в соответствии с названием
класса.
В том, что классы RomanNumber и ArabianNumber унаследовали
свойство Value и метод ShowNumber мы убедились. Теперь будем
изменять метод ShowNumber у классов наследников (сохраняя
сигнатуру метода, что важно) с тем, чтобы вывод чисел
соответствовал требованиям классов RomanNumber и ArabianNumber.
Public Class Number
Public value As Integer
Private Shared Counter As Integer = 0
Public Sub New(ByVal n As Integer)
value = n
Counter += 1
End Sub
Public Sub Dispose()
Counter -= 1
End Sub
Public Shared ReadOnly Property Instances() As Integer
Get
Return Counter
End Get
End Property
Public Overridable Function ShowNumber() As String
Return Me.value.ToString
End Function
End Class
Public Class RomanNumber
Inherits Number
Public Sub New(ByVal n As Integer)
MyBase.New(n)
End Sub
Public Overrides Function ShowNumber() As String
Dim An() As Integer = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
Dim Rn() As String = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX",
"V", "IV", "I"}
Dim i As String = 0
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
20
Dim N = value
Dim Result As String
Do
While An(i) <= N
Result = Result + Rn(i)
N = N - An(i)
End While
i=i+1
Loop While N > 0
Return Result
End Function
End Class
Обратите внимание на модификатор Override в описании
переопределенной функции ShowNumber в классе RomanNumber. В
базовом класса Number, в описании переопределяемой функции
ShowNumber также должен появиться модификатор Overridable.
Самостоятельно
Переопределите функцию ShowNumber для класса ArabianNumber.
Пример тестирования переопределенных методов для классов
наследников см. на рис. 8.
Рис. 8. Тестирование переопределенных методов классов наследников
Задание 8. Практическое использование иерархии классов
Задача
Использовать созданную иерархию классов в Windows-приложении.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
21
Решение
Разработать
и
запрограммировать
интерфейс
приложения,
позволяющего выполнять перевод чисел в разные системы
счисления.
Обсуждение
Для применения классов Number, ArabianNumber и RomanNumber
разработайте пользовательский интерфейс приложения (один из
возможных вариантов приведен на рис. 9).
Рис. 9. Пример интерфейса приложения
Самостоятельно
Используйте созданную иерархию классов для организации работы
приложения.
Задание 9. Абстрактные классы
Задача
Создавать верхний уровень иерархии в виде абстрактного класса, не
имеющего собственных экземпляров.
Решение
Использовать специальные модификаторы для описания абстрактного
класса (MustInherit и MustOverride).
Обсуждение
В нашем примере базовый класс Number является общедоступным, то
есть может быть инициирован любым кодом, определенным вне
заданной иерархии классов. Можно изменить иерархию, сделав
базовый класс Number доступным только для производных классов и
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
22
защищенным от остального кода. Для того чтобы создать такой
абстрактный класс необходимо добавить ключевое слово
MustInherit к оператору описания класса.
Методы и свойства абстрактного класса доступны только через
экземпляры
производных
классов,
экземпляры
собственно
абстрактного класса создавать запрещено.
Если методы абстрактного класса только обозначены, то есть,
описаны их сигнатуры, но не определены операторы, выполняемые
методами, то такие методы в описании абстрактных классов должны
быть помечены ключевым словом MustOverride. Более того,
подобные методы могут иметь только заголовок (сигнатуру), но не
иметь ключевых слов End Function или End Sub. Но таким образом
описанные методы абстрактного класса должны обязательно быть
переопределены в классах наследниках.
Самостоятельно
1. Опишите класс Number как абстрактный класс и
прокомментируйте сообщения об ошибке, возникшей в
предыдущей версии программы (задание 7).
2. Опишите метод ShowNumber() класса Number как метод,
который обязательно подлежит переопределению.
3. Опишите класс RomanNumber как закрытый класс, то есть
класс, который не должен иметь наследников.
4. Протестируйте поведение классов с учетом внесенных
изменений.
Задание 10. Абстрактные классы в стандартных библиотеках
Задача
Рассмотреть применение
библиотеках классов .NET.
абстрактных
классов
в
стандартных
Решение
Изучить иерархию классов System.Drawing.Brush.
Обсуждение
В качестве примера использования иерархии классов, с начальной
вершиной в виде абстрактного класса рассмотрим очень красивую по
реализации иерархию классов Brush (Кисти).
Иерархия
классов
находится
в
пространстве
имен
System.Drawing.Brush, строится на основе базового класса Brush.
Класс Brush является абстрактным классом, то есть создавать
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
23
экземпляры этого класса невозможно. В этом можно убедиться, если
набрать следующий код
Dim br As New Brush (Color.Red)
и увидеть сообщение об ошибке.
Иерархия имеет несколько классов кистей от простых кистей, до
кистей, имеющих довольно сложную фактуру. В качестве примеров
для изучения рассмотрим классы SolidBrush, HatchBrush и
TextureBrush,
хотя,
безусловно,
и
другие
классы
типа
LinearGradientBrush, PathGradientBrush тоже могут стать источником
интересных решений интерфейсов. Напомним, что все эти классы
являются производными от главного абстрактного класса Brush,
который сам непосредственно как инструмент работать не может.
В Windows-форме для обработки события щелчка по командной
кнопке введите следующий код использования сплошных кистей
класса SolidBrush.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim g As Graphics = CreateGraphics()
Dim rect As New Rectangle(10, 10, _
Me.ClientSize.Width - 20, _
Me.ClientSize.Height - 20)
'Создаем зеленую сплошную кисть
Dim sbr As Brush = New System.Drawing.SolidBrush(Color.Green)
'Заполняем прямоугольник зеленой кистью.
g.FillEllipse(sbr, rect)
' Обрамляем прямоугольник эллипсом в 10 пикселов
g.DrawEllipse(New Pen(Color.DarkMagenta, 10), rect)
g.Dispose()
End Sub
Конструктор класса SolidBrush поддерживает и другую модель для
получения цвета – FromARGB. В случае применения этой модели
цветоразрешения кисти могут быть полупрозрачными.
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
Dim g As Graphics = CreateGraphics()
'Создадим три полупрозначные кисти.
Dim trnsRedBrush As New SolidBrush(Color.FromArgb(150, 255, 0, 0))
Dim trnsGreenBrush As New SolidBrush(Color.FromArgb(150, 0, 255, 0))
Dim trnsBlueBrush As New SolidBrush(Color.FromArgb(150, 0, 0, 255))
'Основание и высота треугольника для позиционирования кругов
'Каждая вершина треугольника является центром одного из кругов.
'Основание равно диаметру круга.
Dim triBase As Single = 150
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
24
Dim triHeight As Single = CSng(Math.Sqrt((3*(triBase*triBase) / 4)))
'Координаты для первого круга
Dim x1 As Single = 40
Dim y1 As Single = 40
'Заполняем круги
g.FillEllipse(trnsRedBrush,x1,y1,2*triHeight, 2*triHeight)
g.FillEllipse(trnsGreenBrush, x1 + triBase / 2, y1 + triHeight, 2 * triHeight, 2
* triHeight)
g.FillEllipse(trnsBlueBrush, x1 + triBase, y1, 2 * triHeight, 2 * triHeight)
g.Dispose()
End Sub
Попробуйте запускать проект в разных режимах, поочередно нажимая
командные кнопки. Обратите внимание, что на зеленом фоне
большого эллипса полупрозрачный красный круг получается
коричневым (рис. 10).
Класс HatchBrush представляет собой узорную кисть. Класс
поддерживает более 50 различных узоров (стилей). Используем стиль
HorizontalBrick, который состоит из множества кирпичиков. Не
забывайте, что кисть может иметь не только черно-белую
составляющую, но и любую пару цветов на ваш выбор (рис. 10).
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
'Заполним всю форму кирпичами
Dim hbr As New HatchBrush(HatchStyle.HorizontalBrick,Color.Gray,
Color.Tomato)
Dim g As Graphics = CreateGraphics()
g.FillRectangle(hbr,0,0,ClientSize.Width, ClientSize.Height)
g.Dispose()
End Sub
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
25
Рис. 10. Проект «Кисти»
Класс TextureBrush. Особенностью текстурных кистей, созданных на
основе класса TextureBrush, является использование картинки.
Приведем простой пример применения текстурной кисти (рис. 11).
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim g As Graphics
g = CreateGraphics()
Dim img As Image = Image.FromFile("L:\face.JPG")
Dim tb As New System.Drawing.TextureBrush(img, New Rectangle(0, 0,
60, 88))
tb.WrapMode = Drawing2D.WrapMode.Tile.TileFlipY
g.FillEllipse(tb, 0, 0, 2 * ClientSize.Width \ 3, 2 * ClientSize.Height \ 3)
g.FillRectangle(tb, ClientSize.Width \ 3, ClientSize.Height \
3,ClientSize.Width \ 2, 2 * ClientSize.Height \ 3)
g.Dispose()
End Sub
В этом примере мы создали текстурную кисть, где в качестве картинки
служит изображение из графического файла. У текстурных кистей
существует несколько режимов заполнения. Например, режим
TileFlipY позволяет отразить картинку по горизонтали и размножить
ее, заполняя эллипс и прямоугольник.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
26
Рис. 11. Применение текстурной кисти
Обратите внимание, что, несмотря на наложение этих двух фигур,
рисунки в них совпадают, не перекрывая друг друга (рис. 11). К слову
сказать, текстурные кисти можно вращать, сдвигать, масштабировать.
Поставьте соответствующий вызов перед выводом фигур на экран:
tb.RotateTransform(-35)
Как видите, узор кистей повернулся на тридцать пять градусов.
Самостоятельно
Используя редактор PowerDesigner, создайте диаграмму иерархии
классов Brush.
Задание 11. Применение модификаторов доступа в базовых
классах
Задача
Регулировать доступ к отдельным свойствам и методам класса.
Решение
Использовать специальные модификаторы: Public, Private и Protected.
Обсуждение
При
формировании
иерархической
структуры
классов
с
использованием технологии наследования важно выбрать те свойства
и методы, которые будут доступны в ваших классах. Такой доступ к
отдельным элементам класса регулируется с помощью специальных
модификаторов Public, Private и Protected.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
27
Если метод или свойство базового класса объявляют с ключевым
словом Public, они будут доступны как для производных классов, так и
для кода, определенного за пределами этих классов.
Если метод или свойство объявлены как Private, они будут доступны
только внутри базового класса.
Бывают ситуации, когда нужно разрешить доступ к свойству или
методу из всех производных классов, но запретить доступ к ним кода,
определенного вне этой иерархии. В данном случае следует
применять модификатор доступа Protected.
Самостоятельно
Исследуйте способность перечисленных модификаторов ограничивать
доступ к свойствам и методам базового класса на следующем
примере. Добавьте в описание класса Number метод, позволяющий
делать графический вывод числа. Изменяя уровень доступа к
разработанному методу в классах наследниках с помощью
модификаторов Public, Private и Protected, изучите механизмы
ограничения доступа к этому методу. Пример графического вывода
приведен на рис. 12.
Рис. 12. Пример графического вывода экземпляров иерархии Number
Задание 12. Затенение свойств и методов базового класса
Задача
Регулировать доступ к отдельным свойствам и методам базового
класса.
Решение
Использовать специальный модификатор Shadows.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
28
Обсуждение
Когда производный класс наследует метод базового класса, он может
затенять (shadowing), а не переопределять его. Метод производного
класса, сигнатура которого совпадает с сигнатурой метода базового
класса, затеняет метод базового класса. При этом затеняется не
только метод базового класса, но и все одноименные перегруженные
методы базового класса. Как на практике выполнить затенение
рассмотрим на примере нашей иерархии классов Number,
ArabianNumber и RomanNumber.
Добавим в базовый класс Number Shared-свойство Counter для
подсчета количества созданных экземпляров класса. Доступ к
свойству обеспечим за счет Shared-метода Instances, определенного с
атрибутом ReadOnly.
Public Class Number
Public value As Integer
Private Shared Counter As Integer = 0
Public Sub New(ByVal n As Integer)
value = n
Counter += 1
End Sub
Public Sub Dispose()
Counter -= 1
End Sub
Public Shared ReadOnly Property Instances() As Integer
Get
Return Counter
End Get
End Property
В классе наследнике RomanNumber добавим свойство Counter и
метод Instance, которые будут затенять одноименные свойство и
метод базового класса.
Public Class RomanNumber
Inherits Number
Private Shared Shadows Counter As Integer = 0
Public Sub New(ByVal n As Integer)
MyBase.New(n)
Me.Counter += 1
End Sub
Public Shared Shadows ReadOnly Property Instances() As Integer
Get
Return Counter
End Get
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
29
End Property
А в описании еще одного класса наследника не будем добавлять
никаких переопределяющих или затеняющих свойств, методов. То
есть, этот класс по-прежнему наследует свойство Counter и метод
Instances базового класса (рис. 13).
Рис. 13. Тестирование метода счета количества созданных экземпляров
Public Class ArabianNumber
Inherits Number
Public Sub New(ByVal n As Integer)
MyBase.New(n)
End Sub
Public Overrides Function ShowNumber() As String
Return value.ToString("E")
End Function
End Class
Задание 13. Иерархия классов «Фигуры»
Задача
Разработать собственную иерархию классов, применив все изученные
технологии: абстрактный класс, наследование свойств и методов
класса, перегрузка методов класса, переопределение методов класса,
затенение методов класса, Shared-свойства класса.
Решение
Использовать
все
технологии
объектно-ориентированного
программирования для проектирования иерархического дерева
классов с реализацией наследования, инкапсуляции и полиморфизма.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
Для наглядности
рисования фигур.
проекта
спроектировать
графические
30
методы
Обсуждение
Разработайте иерархию классов для описания геометрических фигур,
например, Окружности, Треугольника, Квадрата, Прямоугольника….
Классы должны описывать свойства фигуры и иметь методы для
вычисления площади и периметра фигуры. В качестве базового
класса сконструируйте абстрактный класс Shape (Фигура). Для
описания свойств классов используйте процедуры описания свойств
(Property). Методы абстрактного класса объявите обязательными для
переопределения. Класс Square (Окружность) объявите закрытым
классом.
Спроектируйте интерфейс приложения для исследования работы
иерархии классов. Примерный вид интерфейса показан на рис. 14.
Рис. 14. Примерный интерфейс приложения
Дополните проект еще одной формой, в которой продемонстрируйте
графические методы классов, позволяющие изображать фигуры.
Для рисования прямоугольника (квадрата) можно использовать
методы DrawRectangle или FillRectangle, для рисования нескольких
прямоугольников удобнее применить методы DrawRectangles или
FillRectangles.
При
использовании
методов с
префиксом
Fill
заданные
прямоугольники закрашиваются кистью заданного цвета. В остальных
случаях рисуется окантовка фигуры. Вот небольшой пример вывода
последовательности синих квадратов по диагонали. Чтобы точно
подогнать квадраты под размеры клиентской области формы зададим
размер формы равным 400400 пикселов.
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
31
Форма для тестирования графических методов фигур может
выглядеть примерно как на рис. 15. Используйте меню для вызова
графических методов различных фигур.
Рис. 15. Тестирование графических методов
Ниже приведен фрагмент кода для рисования квадратов методом
FillRectangles. Код не имеет отношения к методом разрабатываемой
иерархии, вы можете воспользоваться приемами рисования,
показанными в коде программы.
Private Sub Form1_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
ClientSize = New Size(400, 400)
End Sub
Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem2.Click
Dim g As Graphics = CreateGraphics()
Dim rs As Rectangle() = {New Rectangle(0, 0, 100, 100), _
New Rectangle(100, 100, 100, 100), _
New Rectangle(200, 200, 100, 100), _
New Rectangle(300, 300, 100, 100)}
g.FillRectangles(New SolidBrush(Color.Blue), rs)
g.Dispose()
End Sub
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
32
Метод DrawLine позволяет рисовать линии разного цвета и толщины.
При создании линий используйте перо и координаты двух крайних
точек. Так как цвет пера можно создать на основе метода FromARGB.
То у нас есть возможность создавать линии с разным уровнем
прозрачности (рис. 15)
Private Sub MenuItem7_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem7.Click
Dim g As Graphics = CreateGraphics()
Dim clr As New Color
Dim p As New Pen(clr, 5)
g.DrawLine(New Pen((Color.Red), 10), 20, 5, 20, 215)
g.DrawLine(New Pen((Color.Blue), 10), 190, 5, 190, 215)
'выводим ряд горизонтальных линий с изменяющей прозрачностью
Dim i As Integer
For i = 10 To 210 Step 20
p.Color = clr.FromArgb(255 - i, 0, i, 255)
g.DrawLine(p, 10, i, 200, i)
Next
End Sub
Для рисования эллипсов (рис. 15) используйте методы DrawEllipse
или FillEllipse. Метода, рисующего последовательность эллипсов
аналогичного методу DrawRectangles, в VB.NET не существует. Но это
не трудно реализовать самостоятельно, в цикле рисуя вложенные
эллипсы. Приведем фрагмент кода, который вы сможете использовать
для формирования метода рисования эллипса в вашем классе.
Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem3.Click
Dim g As Graphics = CreateGraphics()
Dim p As New Pen(Color.Green)
Dim i As Integer
For i = 0 To 100 Step 5
g.DrawEllipse(p, 10 + i, 10, 200 - 2 * i, 200)
Next
g.Dispose()
End Sub
Для рисования секторов (рис. 15) можно использовать метод FillPie.
Вот так, приблизительно, это реализуется программным способом.
Private Sub MenuItem4_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem4.Click
Dim g As Graphics = CreateGraphics()
Dim sb As New SolidBrush(Color.Yellow)
Dim i As Integer
For i = 0 To 359 Step 120
МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ
INTERNATIONAL BANKING INSTITUTE
33
g.FillPie(sb, 30, 30, 110, 110, i, 60)
Next
g.Dispose()
End Sub
Для рисования дуг используется метод DrawArc. Двойной вызов
метода приводит к следующим результатам (рис.15).
Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem5.Click
Dim g As Graphics = CreateGraphics()
g.DrawArc(New Pen(Color.Red), 100, 70, 300, 300, 90, -180)
g.DrawArc(New Pen(Color.Red), 150, 70, 200, 300, 90, -180)
g.Dispose()
End Sub
И, наконец, многоугольник. Многоугольники задаются массивом точек,
которые соединяются между собой прямыми отрезками с помощью
метода DrawPolygon, причем первая точка массива автоматически
соединяется с последней его точкой (рис. 15).
Private Sub MenuItem6_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MenuItem6.Click
Dim g As Graphics = CreateGraphics()
Dim apts(9) As Point
'Задаем вершины многоугольника
apts(0).X = 180 : apts(0).Y = 70
apts(1).X = 200 : apts(1).Y = 130
apts(2).X = 260 : apts(2).Y = 130
apts(3).X = 220 : apts(3).Y = 170
apts(4).X = 240 : apts(4).Y = 230
apts(5).X = 180 : apts(5).Y = 190
apts(6).X = 120 : apts(6).Y = 230
apts(7).X = 140 : apts(7).Y = 170
apts(8).X = 105 : apts(8).Y = 130
apts(9).X = 160 : apts(9).Y = 130
g.DrawPolygon(Pens.Crimson, apts)
End Sub
Download