Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Если два элемента программирования имеют одно и то же имя, один из них может скрыть или затенить другой. В такой ситуации теневой элемент недоступен для ссылки; вместо этого, когда код использует имя элемента, компилятор Visual Basic разрешает его как затеняющий элемент.
Цель
Основной целью скрытия является защита определения членов вашего класса. Базовый класс может измениться таким образом, что создаст элемент с тем же именем, как у уже определённого. Если это случается, модификатор Shadows
принуждает ссылки через ваш класс разрешаться на определенный вами элемент, вместо того чтобы вести к новому элементу базового класса.
Типы тени
Элемент может затенять другой элемент двумя разными способами. Элемент затенения можно объявить внутри подрегиона региона, содержащего затеняемый элемент, при этом затенение осуществляется через область видимости. Или производный класс может переопределить член базового класса, и в этом случае затенение происходит через наследование.
Тени в пределах области
Элементы программирования в одном модуле, классе или структуре могут иметь одинаковое имя, но разную область видимости. Когда два элемента объявляются подобным образом, и код ссылается на общее имя, элемент с более узкой областью видимости затеняет другой элемент (область блока является самой узкой).
Например, модуль может определить Public
переменную с именем temp
, и процедура в модуле может объявлять локальную переменную также с именем temp
. Ссылки на temp
изнутри процедуры обращаются к локальной переменной, в то время как ссылки на temp
извне процедуры обращаются к переменной Public
. В этом случае переменная процедуры temp
скрывает переменную модуля temp
.
На следующем рисунке показаны две переменные с именами temp
. Локальная переменная temp
скрывает член класса temp
, когда к ней обращаются внутри её собственной процедуры p
. Однако ключевое MyClass
слово проходит тень и обращается к переменной-члену.
Пример сокрытия через область видимости см. в статье "Практическое руководство: Скрыть переменную с таким же именем, как и у вашей переменной".
Затенение через наследование
Если производный класс переопределяет элемент программирования, унаследованный от базового класса, переопределяющий элемент затмевает исходный элемент. Вы можете затмевать любой тип объявленного элемента или любой набор перегруженных элементов, используя любой другой тип. Например, переменная Integer
может затенить процедуру Function
. Если вы замещаете одну процедуру другой, вы можете использовать другой список параметров и другой тип возвращаемого значения.
На следующем рисунке показан базовый класс b
и производный класс d
, наследующий от b
. Базовый класс определяет процедуру с именем proc
, а производный класс заменяет её другой процедурой с тем же именем.
Call
Первая инструкция обращается к тени proc
в производном классе. Однако ключевое MyBase
слово обходит теневой эффект и получает доступ к защищенной процедуре в базовом классе.
Пример теневого наследования см. в статье "Практическое руководство. Скрытие переменной с тем же именем, что и переменная и практическое руководство. Скрытие унаследованной переменной".
Отслеживание и Уровень доступа
Элемент тени не всегда доступен из кода с помощью производного класса. Например, его можно объявить Private
. В таком случае затенение устраняется, и компилятор разрешает проблему с любой ссылкой на тот же элемент, как если бы затенения не существовало. Этот элемент является доступным элементом, который находится на минимальном количестве производных шагов назад от теневого класса. Если теневой элемент является процедурой, разрешение — к ближайшей доступной версии с тем же именем, списком параметров и типом возвращаемого значения.
В следующем примере показана иерархия наследования трех классов. Каждый класс определяет процедуру, и каждый производный класс перекрывает эту процедуру в своем базовом классе.
Public Class firstClass
Public Sub display()
MsgBox("This is firstClass")
End Sub
End Class
Public Class secondClass
Inherits firstClass
Private Shadows Sub display()
MsgBox("This is secondClass")
End Sub
End Class
Public Class thirdClass
Inherits secondClass
Public Shadows Sub display()
MsgBox("This is thirdClass")
End Sub
End Class
Module callDisplay
Dim first As New firstClass
Dim second As New secondClass
Dim third As New thirdClass
Public Sub callDisplayProcedures()
' The following statement displays "This is firstClass".
first.display()
' The following statement displays "This is firstClass".
second.display()
' The following statement displays "This is thirdClass".
third.display()
End Sub
End Module
В предыдущем примере производный класс secondClass
затеняет display
процедурой Private
. Когда модуль callDisplay
вызывает display
в secondClass
, код вызова находится вне secondClass
и поэтому не может получить доступ к закрытой процедуре display
. Проблема теневого связывания решена, и компилятор обращается к процедуре базового класса display
.
Однако дальнейший производный класс thirdClass
объявляет display
как Public
, так что код в callDisplay
может получить к нему доступ.
Затенение и переопределение
Не путайте тени с переопределением. Оба используются, когда производный класс наследует от базового класса, и оба переопределяют один объявленный элемент с другим. Но между этими двумя существуют значительные различия. Сравнение см. в разделе "Различия между теневым и переопределением".
Тень и перегрузка
Если вы скрываете один и тот же элемент базового класса с помощью нескольких элементов в производном классе, элементы скрытия становятся перегруженными версиями этого элемента. Дополнительные сведения см. в разделе "Перегрузка процедур".
Доступ к теневому элементу
При доступе к элементу из производного класса обычно это делается с помощью текущего экземпляра этого производного класса, указав имя элемента с ключевым словом Me
. Если производный класс теняет элемент в базовом классе, вы можете получить доступ к элементу базового класса, квалифицируя его с помощью ключевого MyBase
слова.
Пример доступа к теневой элементу см. в статье "Практическое руководство. Доступ к переменной, скрытой производным классом".
Объявление переменной объекта
Создание переменной объекта также может повлиять на то, обращается ли производный класс к элементу, затмевающему, или к затмеваемому элементу. В следующем примере создаются два объекта из производного класса, но один объект объявлен как базовый класс, а другой — производным классом.
Public Class baseCls
' The following statement declares the element that is to be shadowed.
Public z As Integer = 100
End Class
Public Class dervCls
Inherits baseCls
' The following statement declares the shadowing element.
Public Shadows z As String = "*"
End Class
Public Class useClasses
' The following statement creates the object declared as the base class.
Dim basObj As baseCls = New dervCls()
' Note that dervCls widens to its base class baseCls.
' The following statement creates the object declared as the derived class.
Dim derObj As dervCls = New dervCls()
Public Sub showZ()
' The following statement outputs 100 (the shadowed element).
MsgBox("Accessed through base class: " & basObj.z)
' The following statement outputs "*" (the shadowing element).
MsgBox("Accessed through derived class: " & derObj.z)
End Sub
End Class
В предыдущем примере переменная basObj
объявляется как базовый класс. Назначение dervCls
объекта ему представляет собой расширение преобразования, поэтому является допустимым. Однако базовый класс не может получить доступ к теневой версии переменной z
в производном классе, поэтому компилятор разрешает basObj.z
как первоначальное значение базового класса.