Freigeben über


Schatten in Visual Basic

Wenn zwei Programmierelemente denselben Namen aufweisen, kann eines davon die andere ausblenden oder schatten. In einer solchen Situation steht das schattierte Element nicht zur Referenz zur Verfügung; Wenn ihr Code den Elementnamen verwendet, löst der Visual Basic-Compiler ihn stattdessen in das Schattenelement auf.

Zweck

Der Hauptzweck von Shadowing besteht darin, die Definition Ihrer Klassenmember zu schützen. Die Basisklasse kann sich einer Änderung unterziehen, durch die ein Element mit demselben Namen erstellt wird, den Sie bereits definiert haben. Wenn dies der Fall ist, zwingt der Shadows Modifizierer dazu, dass Verweise durch Ihre Klasse auf das von Ihnen definierte Mitglied aufgelöst werden, anstatt auf das neue Basisklassenelement.

Arten der Schattenbildung

Ein Element kann ein anderes Element auf zwei verschiedene Arten schatten. Das Element, das das Shadowing durchführt, kann in einem Unterbereich des Bereichs deklariert werden, der das dem Shadowing unterzogene Element enthält. In diesem Fall wird das Shadowing über den Gültigkeitsbereich (scope) durchgeführt. Oder eine ableitende Klasse kann ein Element einer Basisklasse neu definieren, in diesem Fall erfolgt die Schattenerstellung durch Vererbung.

Shadowing über den Gültigkeitsbereich

Es ist möglich, dass Programmierelemente in demselben Modul, derselben Klasse oder Struktur denselben Namen, aber einen anderen Bereich aufweisen. Wenn zwei Elemente auf diese Weise deklariert werden und sich der Code auf den Namen bezieht, den sie teilen, überschattet das Element mit dem schmaleren Gültigkeitsbereich das andere Element (Blockbereich ist der schmalste).

Beispielsweise kann ein Modul eine Public Variable namens tempdefinieren, und eine Prozedur innerhalb des Moduls kann eine lokale Variable auch mit dem Namen tempdeklarieren. temp Verweise von innerhalb der Prozedur greifen auf die lokale Variable zu, während Verweise temp von außerhalb der Prozedur auf die Public Variable zugreifen. In diesem Fall schattiert die Prozedurvariable temp die Modulvariable temp.

Die folgende Abbildung zeigt zwei Variablen, die beide benannt sind temp. Die lokale Variable temp führt ein Shadowing durchführen der Membervariablen temp durch, wenn aus ihrer eigenen Prozedur p auf sie zugegriffen wird. Das Schlüsselwort MyClass umgeht jedoch das Shadowing und greift auf die Membervariable zu.

Grafik des Shadowings über den Gültigkeitsbereich.

Ein Beispiel für das Shadowing über den Gültigkeitsbereich finden Sie unter Gewusst wie: Ausblenden einer Variablen mit demselben Namen wie Ihre Variable.

Shadowing durch Vererbung

Wenn eine abgeleitete Klasse ein von einer Basisklasse geerbtes Programmierelement neu definiert, schattiert das neu definierte Element das ursprüngliche Element. Sie können jede Art deklarierter Elemente oder überladene Elemente mit jedem anderen Typ abschatten. Beispielsweise kann eine Integer Variable eine Function Prozedur schatten. Wenn Sie eine Prozedur mit einer anderen Prozedur abschatten, können Sie eine andere Parameterliste und einen anderen Rückgabetyp verwenden.

Die folgende Abbildung zeigt eine Basisklasse b und eine abgeleitete Klasse d, die von b erbt. Die Basisklasse definiert eine Prozedur namens proc, und die abgeleiteten Klassen schatten sie mit einer anderen Prozedur mit demselben Namen. Die erste Call-Anweisung greift auf die das Shadowing durchführende proc der abgeleiteten Klasse zu. Das Schlüsselwort MyBase umgeht jedoch das Shadowing und greift auf die dem Shadowing unterzogene Prozedur in der Basisklasse zu.

Grafikdiagramm der Schattierung durch Vererbung

Ein Beispiel für das Shadowing durch Vererbung finden Sie unter Gewusst wie: Ausblenden einer Variablen mit demselben Namen wie Ihre Variable und Gewusst wie: Ausblenden einer geerbten Variablen.

Shadowing und Zugriffsebene

Auf das Schattenelement kann nicht immer über den Code mithilfe der abgeleiteten Klasse zugegriffen werden. Beispielsweise kann es deklariert Privatewerden. In einem solchen Fall wird das Shadowing außer Kraft gesetzt, und der Compiler löst jeden Verweis auf dasselbe Element auf, das er verwendet hätte, wenn kein Shadowing vorgelegen hätte. Bei diesem Element handelt es sich um das zugängliche Element, das die wenigsten ableitenden Schritte rückwärts von der das Shadowing durchführenden Klasse entfernt ist. Wenn das schattierte Element eine Funktion ist, wird die Auflösung auf die nächstgelegene zugängliche Version mit demselben Namen, derselben Parameterliste und demselben Rückgabetyp vorgenommen.

Das folgende Beispiel zeigt eine Vererbungshierarchie von drei Klassen. Jede Klasse definiert eine Sub Prozedur, und jede abgeleitete Klasse schattiert die display Prozedur displayin ihrer Basisklasse.

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  

Im vorherigen Beispiel überschattet die abgeleitete Klasse secondClassdisplay mit einer Private-Prozedur. Wenn das Modul callDisplay im displaysecondClass aufruft, befindet sich der aufrufende Code außerhalb von secondClass und kann daher nicht auf die private display Prozedur zugreifen. Das Überschatten wird aufgehoben, und der Compiler löst den Verweis auf die Prozedur der Basisklasse display auf.

Die weiter abgeleitete Klasse thirdClass deklariert display als Public, sodass der Code in callDisplay darauf zugreifen kann.

Shadowing und Überschreiben

Verwechseln Sie Shadowing nicht mit Überschreiben. Beide werden verwendet, wenn eine abgeleitete Klasse von einer Basisklasse erbt und beide ein deklariertes Element mit einem anderen neu definieren. Aber es gibt erhebliche Unterschiede zwischen den beiden. Einen Vergleich finden Sie unter Unterschiede zwischen Shadowing und Überschreiben.

Shadowing und Überladen

Wenn Sie das gleiche Basisklassenelement mit mehreren Elementen in der abgeleiteten Klasse schattenn, werden die Schattenelemente zu überladenen Versionen dieses Elements. Weitere Informationen finden Sie unter Prozedurüberladung.

Zugreifen auf ein schatteniertes Element

Wenn Sie auf ein Element aus einer abgeleiteten Klasse zugreifen, erfolgt dies normalerweise über die aktuelle Instanz dieser abgeleiteten Klasse, indem Sie den Elementnamen mit dem Me Schlüsselwort qualifizieren. Wenn ihre abgeleitete Klasse das Element in der Basisklasse schattiert, können Sie auf das Basisklassenelement zugreifen, indem Sie es mit dem MyBase Schlüsselwort qualifizieren.

Ein Beispiel für den Zugriff auf ein schattiertes Element finden Sie unter How to: Access a Variable Hidden by a Derived Class.

Deklaration der Objektvariable

Wie Sie die Objektvariable erstellen, kann sich auch darauf auswirken, ob die abgeleitete Klasse auf ein Schattenelement oder auf das schattierte Element zugreift. Im folgenden Beispiel werden zwei Objekte aus einer abgeleiteten Klasse erstellt, aber ein Objekt wird als Basisklasse und das andere als abgeleitete Klasse deklariert.

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  

Im vorherigen Beispiel wird die Variable basObj als Basisklasse deklariert. Das Zuweisen eines dervCls-Objekts zu dieser Variablen stellt eine erweiternde Konvertierung dar und ist daher gültig. Die Basisklasse kann jedoch nicht auf die Schattenversion der Variablen z in der abgeleiteten Klasse zugreifen, sodass der Compiler basObj.z auf den ursprünglichen Wert der Basisklasse auflöst.

Siehe auch