Skuggning i Visual Basic
När två programmeringselement har samma namn kan den ena dölja eller skugga den andra. I en sådan situation är det skuggade elementet inte tillgängligt som referens. I stället, när koden använder elementnamnet, löser Visual Basic-kompilatorn det till skuggelementet.
Syfte
Huvudsyftet med skuggning är att skydda definitionen av dina klassmedlemmar. Basklassen kan genomgå en ändring som skapar ett element med samma namn som ett som du redan har definierat. Om detta händer Shadows
tvingar modifieraren referenser via klassen att matchas till den medlem som du definierade, i stället för till det nya basklasselementet.
Typer av skuggning
Ett element kan skugga ett annat element på två olika sätt. Skuggningselementet kan deklareras i en underregion i regionen som innehåller det skuggade elementet, i vilket fall skuggningen utförs via omfånget. Eller så kan en härledande klass omdefiniera en medlem i en basklass, i vilket fall skuggningen görs genom arv.
Skuggning genom omfång
Det är möjligt att programmeringselement i samma modul, klass eller struktur har samma namn men ett annat omfång. När två element deklareras på det här sättet och koden refererar till namnet de delar skuggar elementet med det smalare omfånget det andra elementet (blockomfånget är det smalaste).
En modul kan till exempel definiera en Public
variabel med namnet temp
, och en procedur i modulen kan deklarera en lokal variabel med namnet temp
. Referenser till temp
inifrån proceduren kommer åt den lokala variabeln, medan referenser till temp
utanför proceduren kommer åt variabeln Public
. I det här fallet skuggar procedurvariabeln temp
modulvariabeln temp
.
Följande bild visar två variabler, båda med namnet temp
. Den lokala variabeln temp
skuggar medlemsvariabeln temp
när den nås från sin egen procedur p
. Nyckelordet MyClass
kringgår dock skuggningen och kommer åt medlemsvariabeln.
Ett exempel på skuggning genom omfång finns i How to: Hide a Variable with the Same Name as Your Variable (Så här döljer du en variabel med samma namn som din variabel).
Skuggning genom arv
Om en härledd klass omdefinierar ett programmeringselement som ärvts från en basklass skuggar det omdefinierande elementet det ursprungliga elementet. Du kan skugga alla typer av deklarerade element eller uppsättningar överlagrade element med någon annan typ. En variabel kan till exempel Integer
skugga en Function
procedur. Om du skuggar en procedur med en annan procedur kan du använda en annan parameterlista och en annan returtyp.
Följande bild visar en basklass b
och en härledd klass d
som ärver från b
. Basklassen definierar en procedur med namnet proc
, och den härledda klassen skuggar den med en annan procedur med samma namn. Den första Call
instruktionen kommer åt skuggningen proc
i den härledda klassen. Nyckelordet MyBase
kringgår dock skuggningen och kommer åt den skuggade proceduren i basklassen.
Ett exempel på skuggning genom arv finns i How to: Hide a Variable with the Same Name as Your Variable and How to: Hide an Inherited Variable (Så här döljer du en variabel med samma namn som din variabel och gör så här: Dölj en ärvd variabel).
Skuggning och åtkomstnivå
Skuggelementet är inte alltid tillgängligt från koden med hjälp av den härledda klassen. Den kan till exempel deklareras Private
. I sådana fall besegras skuggning och kompilatorn löser alla referenser till samma element som den skulle ha om det inte hade förekommit någon skuggning. Det här elementet är det tillgängliga elementet de minsta härledningsstegen bakåt från skuggningsklassen. Om det skuggade elementet är en procedur är lösningen den närmast tillgängliga versionen med samma namn, parameterlista och returtyp.
I följande exempel visas en arvshierarki med tre klasser. Varje klass definierar en Sub
procedur display
och varje härledd klass skuggar proceduren i basklassen 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
I föregående exempel skuggar display
den härledda klassen secondClass
med en Private
procedur. När modulen callDisplay
anropar display
i secondClass
är den anropande koden utanför secondClass
och kan därför inte komma åt den privata display
proceduren. Skuggning har besegrats och kompilatorn löser referensen till basklassproceduren display
.
Den ytterligare härledda klassen thirdClass
deklarerar display
dock som Public
, så att koden i callDisplay
kan komma åt den.
Skuggning och åsidosättande
Blanda inte ihop skuggning med åsidosättande. Båda används när en härledd klass ärver från en basklass och båda omdefinierar ett deklarerat element med ett annat. Men det finns betydande skillnader mellan de två. En jämförelse finns i Skillnader mellan skuggning och åsidosättande.
Skuggning och överlagring
Om du skuggar samma basklasselement med mer än ett element i din härledda klass blir skuggelementen överbelastade versioner av det elementet. Mer information finns i Överlagring av procedurer.
Komma åt ett skuggat element
När du kommer åt ett element från en härledd klass gör du normalt det via den aktuella instansen av den härledda klassen genom att kvalificera elementnamnet med nyckelordet Me
. Om din härledda klass skuggar elementet i basklassen kan du komma åt basklasselementet genom att kvalificera det med nyckelordet MyBase
.
Ett exempel på hur du kommer åt ett skuggat element finns i Så här använder du en variabel som är dold av en härledd klass.
Deklaration av objektvariabeln
Hur du skapar objektvariabeln kan också påverka om den härledda klassen kommer åt ett skuggelement eller det skuggade elementet. I följande exempel skapas två objekt från en härledd klass, men ett objekt deklareras som basklassen och det andra som den härledda klassen.
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
I föregående exempel deklareras variabeln basObj
som basklass. Att tilldela ett dervCls
objekt till det utgör en bredare konvertering och är därför giltig. Basklassen kan dock inte komma åt skuggningsversionen av variabeln z
i den härledda klassen, så kompilatorn matchar basObj.z
det ursprungliga basklassvärdet.