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

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

Решение проблемы несовместимости версий в .NET Framework в конечном счете основано на том, что ваш класс знает версию DLL, необходимую для его работы, и отказывается работать при отсутствии нужной версии. Успешная работа этого механизма зависит от особых свойств сборок (см. главу 13). Тем не менее.в описанной нами ситуации защита .NET Framework преодолевается простым копированием новой DLL на место старой.

Схема контроля версии в .NET позволяет разработчикам компонентов дополнять свои базовые классы новыми членами (хотя на практике делать этого не рекомендуется). Такая возможность сохраняется даже в том случае, если имена новых членов совпадают с именами членов, включенных вами в производный класс. Старый исполняемый файл, созданный на базе производного класса, продолжает работать, поскольку он не использует новую DLL.

Впрочем, это не совсем верно: он действительно продолжает работать — до тех пор, пока вы не откроете исходный текст приложения Versioningl в VS .NET, создадите ссылку на DLL PayableEntityExample и попробуете построить приложение Versioningl заново. Компилятор выдаст сообщение об ошибке:

C:\book to comp\chapter 5\Versioningl\Versioningl\Modu1el.vb(21):

No argument specified or non-optional parameter 'theAddress' of

'Public Sub New(theName As String,theAddress

As PayableEntityExample.Address)'.

Итак, как только вы загрузите старый исходный текст производного класса и создадите ссылку на новую DLL, вам не удастся откомпилировать программу до исправления той несовместимости, на которую вас обрекли разработчики базового класса.

Прежде чем завершить этот раздел, мы хотим разъяснить еще одно обстоятельство. Исключение конструктора из класса и замена его другим конструктором — весьма грубая и очевидная ошибка. Способен ли механизм контроля версии .NET спасти от других, менее тривиальных ошибок? Да, способен.

Рассмотрим самый распространенный (хотя довольно тривиальный) источник ошибок несовместимости при использовании наследования. Имеется производный класс Derived, зависящий от базового класса Parent. В класс Derived включается новый метод Parselt (в следующем примере он просто разделяет строку по словам и выводит каждое слово в отдельной строке):

Imports Microsoft.VisualBasic.ControlChars Module Modulel

SubMain()

Dim myDerived As New Oerived()

myDerived.DisplayIt 0

Console.ReadLine()

End Sub

End Module

Public Class Parent

Public Const MY STRING As String ="this is a test"

Public Overridable Sub Displaylt()

Console.WriteLine(MY_STRING)

End Sub

End Class

Public Class Derived Inherits Parent

Public Overrides Sub Displaylt()

Console.WriteLine(ParseIt(MyBase.MY_STRING))

End Sub

Public Function ParselUByVal aString As String)

Dim tokens() As String

' Разбить строку по пробелам tokens -

aString.Split(Chr(32))

Dim temp As String

' Объединить в одну строку, вставляя между словами

' комбинацию символов CR/LF

temp = Join(tokens.CrLf)

Return temp

End Function

End Class

End Module

Результат показан на рис. 5.8.

Рис. 5.8. Простейшее разбиение строки по словам

Теперь представьте себе, что класс Parent распространяется не в виде исходных текстов, а в откомпилированной форме. Версия 2 класса Parent содержит собственную версию Parselt, которая широко используется в ее коде. В соответствии с принципом полиморфизма при хранении объекта типа Den ved в объектной переменной типа Parent вызовы Displaylt должны использовать метод Parselt класса Derived вместо метода Parselt базового класса. Однако здесь возникает маловероятная, но теоретически возможная проблема. В нашем сценарии код класса Parent, использующий свою версию функции Parselt, не знает, как функция Parselt реализована в классе Derived. Полиморфный вызов версии Parselt производного класса может нарушить какие-либо условия, необходимые для работы базового класса.

В этой ситуации средства контроля версии VB .NET тоже творят чудеса: код откомпилированного базового класса Parent продолжает использовать свою версию Parselt всегда, даже несмотря на то, что при хранении объектов Derived в переменных типа Parent полиморфизм привел бы к вызову неправильной версии метода. Как упоминалось в предыдущем примере, при открытии кода Derived в Visual Studio компилятор сообщает, что для устранения неоднозначности в объявление метода Parselt производного класса следует включить ключевое слово Override или Shadows.

MFC имеет специальный набор классов, упрощающий процедуру общения с контекстом устройства. Класс CDC содержит большую часть функций, которые могут понадобиться для управления выводом. Классы, производные от CDC, обеспечивают специальные возможности, например класс cciientoc обеспечивает доступ к клиентской области окна, где в основном разворачиваются события, управляемые программистом. Класс CPaintDC позволяет управлять процессом перерисовки окон, обеспечивая вызовы функций BeginPaint и EndPaint в ответ на сообщение WM_PAINT. Создание рисунка в окне производится с помощью функций API, инкапсулированных в одноименных методах класса CDC