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 tempa 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 tempmodulu .

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é.

Graphic that shows shadowing through scope.

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 proca 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ě.

Graphic diagram of shadowing through inheritance

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 displaya 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í secondClassdisplay 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.

Viz také