Udostępnij za pośrednictwem


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 tempmoduł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.

Graphic that shows shadowing through scope.

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

Graphic diagram of shadowing through inheritance

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.

Zobacz też