Stínění v jazyce Visual Basic
Když dva programovací prvky sdílejí stejný název, jeden z nich může skrýt nebo stín, druhý z nich. V takové situaci není stínovaný prvek k dispozici pro referenci; místo toho, když váš kód používá název elementu, kompilátor jazyka Visual Basic jej přeloží na stínovací prvek.
Účel
Hlavním účelem stínování je chránit definici členů třídy. Základní třída může projít změnou, která vytvoří prvek se stejným názvem jako ten, který jste již definovali. Pokud k tomu dojde, Shadows
modifikátor vynutí odkazy prostřednictvím vaší třídy, aby se přeložily na člena, který jste definovali, místo na nový element základní třídy.
Typy stínování
Prvek může stínovat jiný prvek dvěma různými způsoby. Prvek stínování lze deklarovat uvnitř podregionu oblasti obsahující stínovaný prvek, v takovém případě se stínování provádí prostřednictvím oboru. Nebo odvozená třída může předefinovat člen základní třídy, v takovém případě se stínování provádí prostřednictvím dědičnosti.
Stínování prostřednictvím oboru
Programovací prvky ve stejném modulu, třídě nebo struktuře mohou mít stejný název, ale jiný obor. Pokud jsou tímto způsobem deklarovány dva prvky a kód odkazuje na název, který sdílejí, element s užším oborem stínuje druhý prvek (obor bloku je nejužší).
Modul může například definovat proměnnou Public
s názvem temp
a procedura v rámci modulu může deklarovat místní proměnnou také pojmenovanou temp
. Odkazy z procedury přistupí temp
k místní proměnné, zatímco odkazy temp
mimo proceduru Public
přistupí k proměnné. V tomto případě proměnná temp
procedury stínuje proměnnou temp
modulu .
Následující obrázek znázorňuje dvě proměnné, obě pojmenované temp
. Místní proměnná stínuje členovou proměnnou temp
temp
při přístupu z vlastní procedury p
. MyClass
Klíčové slovo však obchází stínování a přistupuje k členské proměnné.
Příklad stínování prostřednictvím oboru najdete v tématu Postupy: Skrytí proměnné se stejným názvem jako vaše proměnná.
Stínování prostřednictvím dědičnosti
Pokud odvozená třída předefinuje programovací prvek zděděný ze základní třídy, redefining element stínuje původní prvek. Můžete stínovat libovolný typ deklarovaného prvku nebo sadu přetížených prvků s jakýmkoli jiným typem. Proměnná Integer
může například stínovat proceduru Function
. Pokud stíníte proceduru s jinou procedurou, můžete použít jiný seznam parametrů a jiný návratový typ.
Následující obrázek znázorňuje základní třídu b
a odvozenou třídu d
, která dědí z b
. Základní třída definuje proceduru s názvem proc
a odvozená třída ji stínuje s jiným postupem stejného názvu. První Call
příkaz přistupuje ke stínování proc
v odvozené třídě. MyBase
Klíčové slovo však obchází stínování a přistupuje ke stínované procedurě v základní třídě.
Příklad stínování dědičnosti najdete v tématu Postupy: Skrytí proměnné se stejným názvem jako proměnná a postupy: Skrytí zděděné proměnné.
Úroveň stínování a přístupu
Stínovací prvek není vždy přístupný z kódu pomocí odvozené třídy. Může být například deklarována Private
. V takovém případě je stínování poraženo a kompilátor vyřeší jakýkoli odkaz na stejný prvek, který by měl, kdyby nedošlo ke stínování. Tento prvek je přístupný prvek nejmenší odvozené kroky zpět od třídy stínování. Pokud stínovaný prvek je procedura, rozlišení je na nejbližší přístupnou verzi se stejným názvem, seznamem parametrů a návratovým typem.
Následující příklad ukazuje hierarchii dědičnosti tří tříd. Každá třída definuje proceduru Sub
display
a každá odvozená třída stínuje proceduru display
v její základní třídě.
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
V předchozím příkladu stíny display
odvozené třídy secondClass
pomocí Private
procedury. Při volání secondClass
display
modulu callDisplay
je volající kód mimosecondClass
, a proto nemůže přistupovat k privátní display
procedurě. Stínování je poraženo a kompilátor přeloží odkaz na proceduru základní třídy display
.
Nicméně, další odvozená třída thirdClass
deklaruje display
jako Public
, aby kód v callDisplay
něm mohl získat přístup.
Stínování a přepsání
Nezaměňujte stínování s přepsáním. Obě se používají, když odvozená třída dědí ze základní třídy a oba předefinují jeden deklarovaný prvek s jiným. Mezi těmito dvěma ale existují významné rozdíly. Porovnání najdete v tématu Rozdíly mezi stínováním a přepsáním.
Stínování a přetížení
Pokud stínujete stejný element základní třídy s více než jedním prvkem v odvozené třídě, stínující prvky se přetíží verze tohoto prvku. Další informace naleznete v tématu Přetížení procedury.
Přístup ke stínovaným elementu
Když přistupujete k elementu z odvozené třídy, obvykle to provedete prostřednictvím aktuální instance této odvozené třídy tím, že opravníte název elementu s klíčovým slovem Me
. Pokud odvozená třída stínuje prvek v základní třídě, můžete k elementu základní třídy získat přístup tím, že ho opravíte pomocí klíčového MyBase
slova.
Příklad přístupu ke stínovaným elementu naleznete v tématu Postupy: Přístup k proměnné skryté odvozenou třídou.
Deklarace proměnné objektu
Způsob vytvoření proměnné objektu může mít vliv také na to, zda odvozená třída přistupuje k elementu stínování nebo stínovaný prvek. Následující příklad vytvoří dva objekty z odvozené třídy, ale jeden objekt je deklarován jako základní třída a druhý jako odvozená třída.
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
V předchozím příkladu je proměnná basObj
deklarována jako základní třída. Přiřazení objektu dervCls
k němu představuje rozšiřující převod, a proto je platný. Základní třída však nemá přístup ke stínové verzi proměnné z
v odvozené třídě, takže kompilátor přeloží basObj.z
na původní hodnotu základní třídy.