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

Замещение

Термин "замещение" (shadowing) встречался и в ранних версиях VB, и в большинстве языков программирования. Локальная переменная, имя которой совпадает с именем переменной, обладающей более широкой областью видимости, замещает (скрывает) эту переменную. Кстати, это одна из причин, по которой переменным уровня модуля обычно присваиваются префиксы m_, а глобальные переменные снабжаются префиксами g_ – грамотный выбор имен помогает избежать ошибок замещения. Переопределение унаследованного метода тоже можно рассматривать как своего рода замещение. В VB.NET поддерживается еще одна, чрезвычайно мощная разновидность замещения:

Член производного класса, помеченный ключевым словом Shadows (которое впервые появилось в бета-версии 2), замещает все одноименные члены базового класса.

При помощи ключевого слова Shadows можно определить в производном классе функцию, имя которой совпадает с именем процедуры базового класса. С практической точки зрения ключевое слово Shadows приводит к тому, что в производном классе появляется абсолютно новый член с заданным именем, в результате чего все одноименные унаследованные члены становятся недоступными в производном классе. Из этого следует, что унаследованные члены класса с ключевым словом Shadows невозможно переопределить, поэтому полиморфизм перестает работать.

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

Иногда замещение усложняет ситуацию и приводит к возникновению нетривиальных ошибок – например, при полиморфном вызове замещенных методов и свойств через объект базового класса. Чтобы рассмотреть эти проблемы на конкретном примере, мы внесем некоторые изменения в класс Programmer:

Public Class Programmer Inherits Employee Private m_gadget As String
Private m_HowToCallMe As String = "Code guru "
Public Sub NewCByVal theName As String, ByVal curSalary As Decimal)
MyBase.New(theName, curSalary)
m_HowToCal1Me = m_HowToCallMe StheName
End Sub
Public Overloads Overrides Sub RaiseSalary(ByVal Percent As Decimal)
MyBase.RaiseSalary(1.2D * Percent, "special")
End Sub
Public Shadows Readonly Property TheName() As String
Get
Return mJtowToCallMe
End Get
End Property
End Class

А теперь попробуйте запустить новый вариант процедуры Sub Main:

Sub Main()
Dim torn As New Employee('Tom". 50000)
Dim sally As New Programmer("Sally". 150000)
Console.WriteLinetsally.TheName)
Dim ourEmployees(l) As Employee
ourEmployees(0)= tom
ourEmployees(l)= sally
Dim anEmployee As Employee
For Each anEmployee In ourEmployees
anEmployee.RaiseSalary(0.lD)
Console.WriteLinetanEmployee.TheName & "salary now is " &
anEmployee. Salary())
Next
Console. ReadLine()
End Sub

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

Иллюстрированный самоучитель по Visual Basic .NET › Наследование и интерфейсы › Замещение
Рис. 5.3. Замещение нарушает работу полиморфных вызовов

Как видно из рисунка, полиморфный вызов перестал работать. Первая строка, выделенная в Sub Main жирным шрифтом, правильно ставит перед именем Sally титул "Code Guru". К сожалению, во второй выделенной строке полиморфизм уже не работает, вследствие чего не вызывается метод TheName производного класса Programmer. Результат – имя выводится без титула.

Другими словами, при использовании ключевого слова Shadows обращения к членам объектов осуществляются в соответствии с типом контейнера, в котором хранится объект, а не их фактическим типом (можно сказать, что при использовании ключевого слова Shadows в производном классе метод или свойство становится невиртуальным).

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.