Udostępnij za pośrednictwem


Cieniowanie w Visual Basic

Gdy dwa elementy programowania mają taką samą nazwę, jeden z nich może ukryć lub zasłonić drugi element. W takiej sytuacji zacieniony element nie jest dostępny do odwołań; zamiast tego, kiedy Twój kod używa nazwy elementu, kompilator języka Visual Basic rozpoznaje ją jako element cieniujący.

Przeznaczenie

Głównym celem zasłaniania 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 modyfikator Shadows wymusza, aby odwołania za pośrednictwem twojej klasy rozpoznawały zdefiniowaną przez ciebie składową, zamiast nowego elementu klasy bazowej.

Typy cieniowania

Element może wyciemnić inny element na dwa różne sposoby. Element cieniujący można zadeklarować wewnątrz podregionu regionu zawierającego element zasłonięty, 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ą dzielą, element z węższym zakresem przesłania drugi element (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 temp zasłania zmienną modułu temp.

Na poniższej ilustracji przedstawiono dwie zmienne o nazwie temp. Zmienna lokalna temp zaciemnia zmienną składową temp kiedy jest używana w swojej własnej procedurze p. Jednak MyClass słowo kluczowe pomija cieniowanie i uzyskuje dostęp do zmiennej składowej.

Grafika przedstawiająca cieniowanie przez lunetę.

Aby zapoznać się z przykładem ukrywania zmiennej w zakresie, zobacz Jak ukryć zmienną o tej samej nazwie, co Twoja zmienna.

Cieniowanie przez dziedziczenie

Jeśli klasa pochodna przeprogramowuje element programistyczny dziedziczony z klasy bazowej, przeprogramowany element zasłania oryginalny element. 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 . Jeśli nadpiszesz procedurę inną procedurą, możesz użyć innej listy parametrów i innego typu zwracanego.

Poniższa ilustracja przedstawia klasę b bazową i klasę pochodną, która dziedziczy z dklasy b . 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 słowo kluczowe MyBase pomija cieniowanie i uzyskuje dostęp do zacienionej procedury w klasie bazowej.

Graficzny diagram cieniowania po dziedziczeniu

Aby zapoznać się z przykładem cieniowania przez dziedziczenie, zobacz Jak: ukryć zmienną o takiej samej nazwie jak Twoja zmienna i Jak: ukryć dziedziczoną 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 zacieniowany element jest procedurą, rozwiązanie polega na wybraniu najbliższej dostępnej wersji o tej samej nazwie, liście parametrów i typie zwracanym.

W poniższym przykładzie przedstawiono hierarchię dziedziczenia trzech klas. Każda klasa definiuje procedurę Sub, a każda klasa pochodna cieniuje display procedurę display 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 klasa pochodna secondClass cieniowała display za pomocą procedury Private. Gdy moduł callDisplay wywołuje display w secondClass, kod wywołujący znajduje się poza secondClass i dlatego nie może uzyskać dostępu do prywatnej procedury display. Cieniowanie zostanie pokonane, a kompilator rozpozna odwołanie do procedury klasy display bazowej.

Jednak dalsza klasa thirdClass pochodna deklaruje display jako Public, więc kod w callDisplay może go uzyskać.

Zasłanianie i zastępowanie

Nie należy mylić cieniowania z zastępowaniem. Zarówno jedna, jak i druga są używane, gdy klasa pochodna dziedziczy z klasy bazowej, i obie zastępują jeden zadeklarowany element 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 ukrywania tego samego elementu klasy bazowej przez więcej niż jeden element w klasie pochodnej, elementy ukrywające stają się przeciążonymi wersjami tego elementu. Aby uzyskać więcej informacji, zobacz Przeciążenie procedury.

Uzyskiwanie dostępu do zacienionego elementu

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 przesłaniającego, czy elementu przesłoniętego. 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 obiektu dervCls do niego 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 rozwiązuje basObj.z do oryginalnej wartości klasy bazowej.

Zobacz także