Przesłanianie w Visual Basic
Gdy dwa elementy programowania mają taką samą nazwę, jedna z nich może ukryć lub ukryć cień, drugi. W takiej sytuacji niezaciemniony element nie jest dostępny do odwołania; Zamiast tego, gdy kod używa nazwy elementu, kompilator języka Visual Basic rozpoznaje go w elemecie cieniowania.
Purpose
Głównym celem cieniowania jest ochrona definicji składowych klasy. Klasa bazowa może przejść zmianę, która tworzy element o takiej samej nazwie jak ta, która została już zdefiniowana. W takim przypadku Shadows
modyfikator wymusza odwołanie za pośrednictwem klasy do rozpoznania zdefiniowanej składowej zamiast do nowego elementu klasy bazowej.
Typy cieniowania
Element może wyciemnić inny element na dwa różne sposoby. Element cieniowania można zadeklarować wewnątrz podregionu regionu zawierającego element w tle, w którym to przypadku cieniowanie jest realizowane za pomocą zakresu. Lub klasa wyprowadzająca może ponownie zdefiniować składową klasy bazowej, w tym przypadku cieniowanie odbywa się przez dziedziczenie.
Cieniowanie przez zakres
Istnieje możliwość, aby elementy programowania w tym samym module, klasie lub strukturze miały taką samą nazwę, ale inny zakres. Gdy dwa elementy są deklarowane w ten sposób i kod odwołuje się do nazwy, którą współużytkują, element z węższym zakresem w tle drugiego elementu (zakres bloku jest najwęższy).
Na przykład moduł może zdefiniować zmienną Public
o nazwie temp
, a procedura w module może zadeklarować zmienną lokalną o nazwie temp
. Odwołania do z wewnątrz procedury uzyskują dostęp do temp
zmiennej lokalnej, a odwołania do spoza procedury uzyskują dostęp do temp
zmiennej Public
. W tym przypadku zmienna procedury w tle zmienna temp
temp
modułu .
Na poniższej ilustracji przedstawiono dwie zmienne o nazwie temp
. Zmienna lokalna w tle zmienną temp
temp
składową, gdy uzyskuje dostęp z jej własnej procedury p
. Jednak MyClass
słowo kluczowe pomija cieniowanie i uzyskuje dostęp do zmiennej składowej.
Aby zapoznać się z przykładem cieniowania w zakresie, zobacz How to: Hide a Variable with the Same Name as Your Variable (Jak: ukrywanie zmiennej o tej samej nazwie co zmienna).
Cieniowanie przez dziedziczenie
Jeśli klasa pochodna ponownie definiuje element programowania dziedziczony z klasy bazowej, element ponownego definiowania w tle oryginalnego elementu. Można cieniować dowolny typ zadeklarowanego elementu lub zestaw przeciążonych elementów z dowolnym innym typem. Na przykład zmienna Integer
może wyciemnić procedurę Function
. W przypadku cienia procedury z inną procedurą można użyć innej listy parametrów i innego typu zwracanego.
Poniższa ilustracja przedstawia klasę b
bazową i klasę pochodną, która dziedziczy z b
klasy d
. Klasa bazowa definiuje procedurę o nazwie proc
, a klasa pochodna cieniuje ją inną procedurą o tej samej nazwie. Pierwsza Call
instrukcja uzyskuje dostęp do cieniowania proc
w klasie pochodnej. Jednak MyBase
słowo kluczowe pomija cieniowanie i uzyskuje dostęp do procedury w tle w klasie bazowej.
Aby zapoznać się z przykładem cieniowania dziedziczenia, zobacz Jak: ukrywać zmienną o takiej samej nazwie jak Zmienna i Jak: ukrywać dziedziczona zmienną.
Poziom cieniowania i dostępu
Element cieniowania nie zawsze jest dostępny z kodu przy użyciu klasy pochodnej. Na przykład może zostać zadeklarowany .Private
W takim przypadku cieniowanie zostanie pokonane, a kompilator rozpozna wszelkie odwołania do tego samego elementu, który miałby, gdyby nie było cieniowania. Ten element jest dostępnym elementem najmniejszych kroków pochodnych do tyłu z klasy cieniowania. Jeśli w tle element jest procedurą, rozdzielczość jest najbliższą dostępną wersją o tej samej nazwie, liście parametrów i zwracanym typie.
W poniższym przykładzie przedstawiono hierarchię dziedziczenia trzech klas. Każda klasa definiuje procedurę display
, a każda klasa pochodna cieniuje display
procedurę Sub
w swojej klasie bazowej.
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
W poprzednim przykładzie cienie display
klasy secondClass
pochodnej z procedurąPrivate
. Gdy moduł callDisplay
wywołuje display
metodę w programie secondClass
, kod wywołujący znajduje się poza secondClass
i dlatego nie może uzyskać dostępu do procedury prywatnej display
. Cieniowanie zostanie pokonane, a kompilator rozpozna odwołanie do procedury klasy display
bazowej.
Jednak dalsza klasa thirdClass
pochodna deklaruje jako display
Public
, aby kod w callDisplay
pliku mógł uzyskać do niej dostęp.
Cieniowanie i zastępowanie
Nie należy mylić cieniowania z zastępowaniem. Oba są używane, gdy klasa pochodna dziedziczy z klasy bazowej, a obie definiują jeden zadeklarowany element z innym. Ale istnieją znaczące różnice między nimi. Aby zapoznać się z porównaniem, zobacz Różnice między cieniowaniem i zastępowaniem.
Cieniowanie i przeciążenie
W przypadku cieniowania tego samego elementu klasy bazowej z więcej niż jednym elementem w klasie pochodnej elementy cieniowania stają się przeciążone wersje tego elementu. Aby uzyskać więcej informacji, zobacz Przeciążenie procedury.
Uzyskiwanie dostępu do elementu w tle
Gdy uzyskujesz dostęp do elementu z klasy pochodnej, zwykle wykonujesz to za pośrednictwem bieżącego wystąpienia tej klasy pochodnej, kwalifikując nazwę elementu za pomocą słowa kluczowego Me
. Jeśli klasa pochodna zaciemnia element w klasie bazowej, możesz uzyskać dostęp do elementu klasy bazowej, kwalifikując go za pomocą słowa kluczowego MyBase
.
Aby zapoznać się z przykładem uzyskiwania dostępu do zaciemnionego elementu, zobacz Jak uzyskać dostęp do zmiennej ukrytej przez klasę pochodną.
Deklaracja zmiennej obiektu
Sposób tworzenia zmiennej obiektu może również mieć wpływ na to, czy klasa pochodna uzyskuje dostęp do elementu cieniowania, czy elementu w tle. Poniższy przykład tworzy dwa obiekty z klasy pochodnej, ale jeden obiekt jest zadeklarowany jako klasa bazowa, a drugi jako klasa pochodna.
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
W poprzednim przykładzie zmienna basObj
jest zadeklarowana jako klasa bazowa. Przypisanie dervCls
do niego obiektu stanowi konwersję rozszerzającą i dlatego jest prawidłowe. Jednak klasa bazowa nie może uzyskać dostępu do wersji cieniowania zmiennej z
w klasie pochodnej, więc kompilator rozpoznaje basObj.z
oryginalną wartość klasy bazowej.