Иллюстрированный самоучитель по Visual Basic .NET

Проблема неустойчивости базовых классов и контроль версии

Проблема несовместимости компонентов хорошо известна всем, кому доводилось программировать для Windows. Обычно она выступает в форме так называемого кошмара DLL (DLL Hell) – программа использует определенную версию DLL, a потом установка новой версии компонента нарушает работу программы. Почему? Причины могут быть разными, от очевидных (случайное исключение функции, использовавшейся в программе) до весьма нетривиальных (например, изменение типа возвращаемого значения у функции). В любом случае все сводится к вариациям на одну тему – при изменении открытого интерфейса кода, от которого зависит ваша программа, программа не может использовать новую версию вместо старой, а старая версия уже стерта.

В большинстве объектно-ориентированных языков наследование сопряжено с потенциальной угрозой работоспособности вашей программы из-за несовместимости компонентов. Программисту остается лишь надеяться на то, что открытые и защищенные члены классов-предшественников в иерархии наследования не будут изменяться, таким образом, что это нарушит работоспособность их программ. Эта ситуация называется проблемой неустойчивости базовых классов. Наследование часто превращает наши программы в некое подобие карточного домика – попробуйте вытащить нижнюю карту, и все сооружение развалится.

Проблему неустойчивости базовых классов желательно рассмотреть на конкретном примере. Разместите приведенное ниже определение класса PayableEntity в отдельной библиотеке и откомпилируйте его в сборку с именем PayableEntityExample командой Build (чтобы задать имя сборки, щелкните правой кнопкой мыши на имени проекта в окне решения, выберите в контекстном меню команду Properties и введите нужные значения в диалоговом окне). Если вы не используете архив с примерами, прилагаемый к книге, запомните, в каком каталоге был построен проект:

Public Mustlnherit Class PayableEntity
Private m_Name As String
Public Sub New(ByVal theName As String)
m_Name =theName
End Sub
Public Readonly Property TheName()As String Get
Return m_Name
End Get
End Property
Public MustOverride
Property TaxID()As
String
End Class

После построения DLL закройте решение.

Допустим, вы решили включить в класс Employee новый способ получения адреса, зависящий от базового класса PayableEntity; при этом следует помнить, что класс будет использоваться только в откомпилированной форме. Для этого необходимо включить ссылку на сборку, содержащую этот проект (находится в подкаталоге \bin того каталога, в котором была построена DLL PayableEntityExample). Примерный код класса Employee приведен ниже. Обратите внимание на строку, выделенную жирным шрифтом, в которой класс объявляется производным от абстрактного класса, определенного в сборке PayableEntityExample.

Public Class Employee
' Пространство имен называется PayableEntityExample.
' поэтому полное имя класса записывается в виде
PayableEntityExample.PayableEntity! Inherits
PayableEntityExample.Employee
Private m_Name As String
Private m_Salary As Decimal
Private m_Address As String
Private m_TaxID As String
Private Const LIMIT As Decimal = 0.1D
Public Sub New(ByVal theName As String,
ByVal curSalary As Decimal,
ByVal TaxID As String)
MyBase.New(theName)
m_Name = theName
m_Salary = curSalary
m_TaxID = TaxID
End Sub
Public Property Address()As String
Get
Return m_Address
End Get
Set(ByVal Value As String)
m_Address = Value
End Set
End Property
Public Readonly Property Salary()As Decimal Get
Return m_Salary
End Get
End Property
Public Overrides Property TaxIDO As String Get
Return m_TaxID
End Get
SetCByVal Value As String)
If Value.Length <> 11 Then
' См. главу 7 Else
m_TaxID = Value
End If
End Set
End Property
End Class
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.