Учебник Visual Basic .NET Выражения, операторы Классы и объекты Наследование и интерфейсы Обработка событий и делегаты Обработка ошибок Формы Windows Ввод-вывод Многопоточные приложения Поддержка баз данных Обзор ASP .NET

Заметьте, что и World space и Page space измеряют плоскую область, размах которой по обеим координатам равняется 2 32 логических единиц, то есть более 4 миллиардов единиц. Page space работает совместно с Device space, чтобы обеспечить приложение единицами, не зависящими от типа физического устройства, такими как миллиметры и дюймы-(inches). Конечным координатным пространством, Physical Device space обычно является клиентская область окна приложения, или весь экран монитора, или страница бумаги принтера (плоттера). Размеры области физического устройства изменяются в зависимости от марки, технологии и т. д. Чтобы верно передать детали изображения, созданного в логической системе, в физическое устройство, система преобразовывает их путем отображения (mapping) прямоугольной области из одного координатного пространства в другое. При копировании каждой точки прямоугольной области из одного пространства в другое Windows применяет алгоритм трансформации, который в конечном счете изменяет размеры, ориентацию и форму всего объекта.

Пример: класс CollectionBase

При использовании классов коллекций .NET Framework (таких, как ArrayList и HashTable) возникает неожиданная проблема: эти классы предназначены для хранения обобщенного типа Object, поэтому прочитанные из них объекты всегда приходится преобразовывать к исходному типу функцией СТуре. Также возникает опасность того, что кто-нибудь сохранит в контейнере объект другого типа и попытка вызова СТуре завершится неудачей. Проблема решается использованием коллекций с сильной типизацией — контейнеров, позволяющих хранить объекты конкретного типа и типов, производных от него.

Хорошим примером абстрактного базового класса .NET Framework является класс CollectionBase. Классы, производные от Coll ectionBase, используются для построения коллекций с сильной типизацией (прежде чем создавать собственные классы коллекций, производные от Coll ectionBase, убедитесь в том, что нужные классы отсутствуют в пространстве имен System.Collections.Specialized). Коллекции, безопасные по отношению к типам, строятся на основе абстрактного базового класса System. Collections. CollectionBase; от вас лишь требуется реализовать методы Add и Remove, а также свойство Item. Хранение данных во внутреннем списке реализовано на уровне класса System. Collections. CollectionBase, который и выполняет все остальные операции.

Рассмотрим пример создания специализированных коллекций (предполагается, что проект содержит класс Employee или ссылку на него):

1 Public Class Employees

2 Inherits System.Col lections.CollectionBase

3 ' Метод Add включает в коллекцию только объекты класса Employee.

4 ' Вызов перепоручается методу Add внутреннего объекта List.

5 Public Sub AddtByVal aEmployee As Employee)

6 List.Add(aEmployee)

7 End Sub

8 Public Sub Remove(ByVal index As Integer)

9 If index > Count-1 Or index < 0 Then

10 ' Индекс за границами интервала, инициировать исключение (глава 7)

11 MsgBox("Can't add this item")' MsgBox условно заменяет исключение

12 Else

13 List.RemoveAt(index)

14 End If

15 End Sub

16

17 Default Public Readonly Property Item(ByVal index As Integer)As Employee

18 Get

19 Return CType(List.Item(index). Employee)

20 End Get

21 End Property

22 End Class

В строках 5-7 абстрактный метод Add базового класса реализуется передачей вызова внутреннему объекту List; метод принимает для включения в коллекцию только объекты Empl oyee. В строках 8-10 реализован метод Remove. На этот раз мы также используем свойство Count внутреннего объекта List, чтобы убедиться в том, что удаляемый объект не находится перед началом или после конца списка. Наконец, свойство Item реализуется в строках 17-21. Оно объявляется свойством по умолчанию, поскольку пользователи обычно ожидают от коллекций именно такого поведения. Свойство объявляется доступным только для чтения, чтобы добавление новых элементов в коллекцию могло осуществляться только методом Add. Конечно, свойство можно было объявить и доступным для чтения/записи, но тогда потребовался бы дополнительный код для проверки индекса добавляемого элемента. Следующий фрагмент проверяет работу специализированной коллекции; недопустимая операция включения нового элемента (в строке, выделенной жирным шрифтом) закомментирована:

Sub Main()

Dim torn As New Employee("Tom", 50000)

Dim sally As New Employee("Sally", 60000)

Dim myEmployees As New Employees()

myEmployees.Add(tom)

myEmployees.Add(sally)

' myEmployees.Add("Tom")

Dim aEmployee As Employee

For Each aEmployee In myEmployees

Console.WriteLine(aEmployee.TheName)

Next

Console. ReadLine()

End Sub

Попробуйте убрать комментарий из строки myEmpl oyees. Add("Tom"). Программа перестанет компилироваться, и вы получите следующее сообщение об ошибке:

C:\book to comp \chapter 5\EmployeesClass\EmployeesClass\Modulel.vb(9):

A value of type 'String'cannot be converted to 'EmployeesClass.Employee'.

Перед вами замечательный пример того, какими преимуществами VB .NET обладает перед включением в прежних версиях VB. Конечно, мы продолжаем перепоручать вызовы внутреннему объекту, чтобы избавиться от дополнительной работы, но возможность перебора элементов в цикле For-Each появляется автоматически, поскольку наш класс является производным от класса с поддержкой For-Each!

Зададимся целью внести изменения в приложение My, которое мы создали в предыдущей главе, таким образом, чтобы изображение геометрической фигуры всегда было в центре окна и следило за изменением размеров окна приложения, меняясь пропорционально. Напомним, что фигурой является многоугольник с произвольным количеством вершин, и он выводится в контекст устройства Windows с помощью объекта класса CDC. Для того чтобы упростить процесс слежения за размерами окна представления, введем в число членов класса CMyView новую переменную, которая будет хранить текущие размеры окна.