Сокрытие в Visual Basic
Если два элемента программирования имеют одно и то же имя, один из них может скрыть или тень, другой. В такой ситуации теневой элемент недоступен для ссылки; Вместо этого, когда код использует имя элемента, компилятор 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
. В таком случае тень побеждена, и компилятор разрешает любую ссылку на тот же элемент, который он имел бы, если бы не было тени. Этот элемент является доступным элементом, который является наименьшим производным шагом назад от теневой класса. Если теневой элемент является процедурой, разрешение — к ближайшей доступной версии с тем же именем, списком параметров и типом возвращаемого значения.
В следующем примере показана иерархия наследования трех классов. Каждый класс определяет процедуру, а каждый производный Sub
класс тени display
процедуры display
в базовом классе.
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
. При вызове display
secondClass
модуля callDisplay
код вызова находится вне secondClass
и поэтому не может получить доступ к частной display
процедуре. Тень побеждена, и компилятор разрешает ссылку на процедуру базового класса display
.
Однако дальнейший производный класс thirdClass
объявляется display
как Public
, поэтому код в callDisplay
нем может получить доступ.
Тень и переопределение
Не путайте тени с переопределением. Оба используются, когда производный класс наследует от базового класса, и оба переопределяют один объявленный элемент с другим. Но между этими двумя существуют значительные различия. Сравнение см. в разделе "Различия между теневым и переопределением".
Тень и перегрузка
Если вы тенируете один и тот же элемент базового класса с несколькими элементами в производном классе, теневые элементы становятся перегруженными версиями этого элемента. Дополнительные сведения см. в разделе Procedure Overloading.
Доступ к теневому элементу
При доступе к элементу из производного класса обычно это выполняется с помощью текущего экземпляра этого производного класса, присвоив имя элемента ключевое слово 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
исходное значение базового класса.