Shadowing in Visual Basic
Wenn zwei Programmierelemente denselben Namen aufweisen, kann eins davon das andere durch so genanntes Shadowing verbergen. In einer solchen Situation ist das Element, für das ein solches Shadowing durchgeführt wurde, nicht für Verweise verfügbar. Wenn Ihr Code den Namen dieses Elements verwendet, löst der Visual Basic-Compiler den Namen stattdessen in das Element auf, das das Shadowing durchführt.
Zweck
Der Hauptzweck von Shadowing besteht darin, die Definition Ihrer Klassenmember zu schützen. Die Basisklasse kann eine Änderung erfahren, durch die ein Element mit demselben Namen wie dem eines bereits definierten Elements erstellt wird. In diesem Fall erzwingt der Shadows
-Modifizierer, dass Verweise über Ihre Klasse in den von Ihnen definierten Member aufgelöst werden, anstatt in das neue Basisklassenelement.
Typen des Shadowings
Ein Element kann das Shadowing für ein anderes Element auf zwei verschiedene Arten durchführen. 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 einen Member einer Basisklasse neu definieren. In diesem Fall erfolgt das Shadowing durch Vererbung.
Shadowing über den Gültigkeitsbereich
Es ist möglich, dass Elemente im selben Modul, in derselben Klasse oder Struktur denselben Namen, aber einen unterschiedlichen Gültigkeitsbereich haben. Wenn zwei Elemente auf diese Weise deklariert werden und der Code auf den Namen verweist, den sie gemeinsam haben, führt das Element mit dem engeren Gültigkeitsbereich ein Shadowing des anderen Elements durch (Blockbereich ist der engste).
Beispielsweise kann ein Modul eine Public
-Variable mit dem Namen temp
definieren, und eine Prozedur innerhalb des Moduls kann eine lokale Variable ebenfalls mit dem Namen temp
deklarieren. Verweise auf temp
aus der Prozedur heraus greifen auf die lokale Variable zu, während Verweise auf temp
von außerhalb der Prozedur auf die Public
-Variable zugreifen. In diesem Fall führt die Prozedurvariable temp
ein Shadowing der Modulvariablen temp
durch.
Die folgende Abbildung zeigt zwei Variablen, beide mit dem Namen 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.
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, führt das neu definierende Element ein Shadowing des ursprünglichen Elements durch. Sie können für jeden Typ von deklarierten Elementen und jeden Satz überladener Elemente ein Shadowing mit jedem anderen Typ durchführen. Beispielsweise kann eine Integer
-Variable ein Shadowing einer Function
-Prozedur durchführen. Wenn Sie ein Shadowing einer Prozedur mit einer anderen Prozedur durchführen, 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 mit dem Namen proc
, und die abgeleitete Klasse führt ein Shadowing dieser Prozedur mit einer anderen Prozedur desselben Namens durch. 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.
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 Element, das das Shadowing durchführt, kann nicht immer aus dem Code mithilfe der abgeleiteten Klasse zugegriffen werden. Beispielsweise könnte es als Private
deklariert sein. 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 es sich bei dem dem Shadowing unterzogenen Element um eine Prozedur handelt, erfolgt die Auflösung in die nächstgelegene zugängliche Version mit demselben Namen, derselben Parameterliste und demselben Rückgabetyp.
Das folgende Beispiel zeigt eine Vererbungshierarchie von drei Klassen. Jede Klasse definiert eine Sub
-Prozedur display
, und jede abgeleitete Klasse führt ein Shadowing der display
-Prozedur in ihrer Basisklasse durch.
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 führt die abgeleitete Klasse secondClass
ein Shadowing von display
mit einer Private
-Prozedur durch. Wenn das callDisplay
-Modul display
in secondClass
aufruft, befindet sich der aufrufende Code außerhalb von secondClass
und kann daher nicht auf die private display
-Prozedur zugreifen. Das Shadowing wird außer Kraft gesetzt, und der Compiler löst den Verweis auf die display
-Prozedur der Basisklasse auf.
Die weiter abgeleitete thirdClass
-Klasse deklariert jedoch 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 definieren ein deklariertes Element mit einem anderen neu. Es bestehen allerdings erhebliche Unterschiede zwischen den beiden. Einen Vergleich finden Sie unter Unterschiede zwischen Shadowing und Überschreiben.
Shadowing und Überladen
Wenn Sie ein Shadowing desselben Basisklassenelements mit mehr als einem Element in Ihrer abgeleiteten Klasse durchführen, werden die das Shadowing durchführenden Elemente zu überladenen Versionen dieses Elements. Weitere Informationen finden Sie unter Procedure Overloading.
Zugreifen auf ein dem Shadowing unterzogenes Element
Wenn Sie auf eine Element aus einer abgeleiteten Klasse zugreifen, geschieht dies normalerweise über die aktuelle Instanz dieser abgeleiteten Klasse, indem Sie den Elementnamen mit dem Schlüsselwort Me
qualifizieren. Wenn Ihre abgeleitete Klasse ein Shadowing des Elements in der Basisklasse durchführt, können Sie auf das Basisklassenelement zugreifen, indem Sie es mit dem Schlüsselwort MyBase
qualifizieren.
Ein Beispiel für den Zugriff auf ein dem Shadowing unterzogenes Element finden Sie unter Gewusst wie: Zugreifen auf eine von einer abgeleiteten Klasse ausgeblendete Variable.
Deklaration der Objektvariablen
Die Art, wie Sie die Objektvariable erstellen, kann sich auch darauf auswirken, ob die abgeleitete Klasse auf ein das Shadowing durchführendes Element oder auf das dem Shadowing unterzogene Element zugreift. Im folgenden Beispiel werden zwei Objekte aus einer abgeleiteten Klasse erstellt, aber ein Objekt wird als die Basisklasse und das andere als die 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 die 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 as Shadowing durchführende Version der Variablen z
in der abgeleiteten Klasse zugreifen, sodass der Compiler basObj.z
in den ursprünglichen Basisklassenwert auflöst.