Occultation dans Visual Basic
Lorsque deux éléments de programmation partagent le même nom, l’un d’entre eux peut masquer ou mettre l’autre en mémoire fantôme. Dans une telle situation, un élément ombré n’est pas disponible pour référence ; au lieu de cela, lorsque votre code utilise le nom de l’élément, le compilateur Visual Basic le résout en élément d’ombre.
Objectif
L’objectif principal de l’ombre est de protéger la définition de vos membres de classe. La classe de base peut subir une modification qui crée un élément portant le même nom qu'un élément que vous avez déjà défini. Dans ce cas, le modificateur Shadows
force les références via votre classe à résoudre en membre que vous avez défini, au lieu du nouvel élément de classe de base.
Types d’ombre
Un élément peut ombrer un autre élément de deux façons différentes. L’élément d’ombre peut être déclaré à l’intérieur d’une sous-région contenant l’élément ombré, auquel cas l’ombre est effectuée à travers l’étendue. Ou une classe dérivante peut redéfinir un membre d’une classe de base, auquel cas l’ombre est effectuée via l’héritage.
Ombre à travers l’étendue
Il est possible que les éléments de programmation dans le même module, classe ou structure aient le même nom mais une étendue différente. Lorsque deux éléments sont déclarés de cette façon et que le code fait référence au nom qu’ils partagent, l’élément avec l’étendue plus restrictive ombre l’autre élément (l’étendue de bloc est la plus restrictive).
Par exemple, un module peut définir une variable Public
nommée temp
, et une procédure dans le module peut déclarer une variable locale également nommée temp
. Les références à temp
à l'intérieur de la procédure accèdent à la variable locale, tandis que les références à temp
à l'extérieur de la procédure accèdent à la variable Public
. Dans ce cas, la variable de procédure temp
ombre la variable de module temp
.
L’illustration suivante montre deux variables nommées temp
. La variable locale temp
ombre la variable membre temp
lorsqu’elle est accédée à partir de sa propre procédure p
. Toutefois, le mot clé MyClass
contourne l’ombre et accède à la variable membre.
Pour obtenir un exemple d’ombre à travers l’étendue, consultez Comment : masquer une variable portant le même nom que votre variable.
Ombre via l’héritage
Si une classe dérivée redéfinit un élément de programmation hérité d’une classe de base, l’élément de redéfinition ombre l’élément d’origine. Vous pouvez ombrer n’importe quel type d’élément déclaré, ou ensemble d’éléments surchargés, avec n’importe quel autre type. Par exemple, une variable Integer
peut ombrer une procédure Function
. Si vous ombrez une procédure avec une autre procédure, vous pouvez utiliser une liste de paramètres différente et un autre type de retour.
L’illustration suivante montre une classe de base b
et une classe dérivée d
qui hérite de b
. La classe de base définit une procédure nommée proc
et la classe dérivée l’ombre avec une autre procédure du même nom. La première instruction Call
accède au proc
d’ombre dans la classe dérivée. Toutefois, le mot clé MyBase
contourne l’ombre et accède à la procédure ombrée dans la classe de base.
Pour obtenir un exemple d’ombre par héritage, consultez Comment : masquer une variable portant le même nom que votre variable et Comment : masquer une variable héritée.
Ombre et niveau d’accès
L’élément d’ombre n’est pas toujours accessible à partir du code à l’aide de la classe dérivée. Par exemple, il peut être déclaré Private
. Dans ce cas, l’ombre est rejeté et le compilateur résout toute référence au même élément qu’il aurait s’il n’y avait pas eu d’ombre. L’élément est celui accessible qui est le moins éloigné de la classe d’ombre. Si l'élément ombré est une procédure, la résolution se fait sur la version accessible la plus proche ayant le même nom, la même liste de paramètres et le même type de retour.
L’exemple suivant montre une hiérarchie d’héritage de trois classes. Chaque classe définit une procédure Sub
display
, et chaque classe dérivée ombre la procédure display
dans sa classe de base.
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
Dans l’exemple précédent, la classe dérivée secondClass
ombre display
avec une procédure Private
. Lorsque le module callDisplay
appelle display
dans secondClass
, le code appelant est en dehors de secondClass
et ne peut donc pas accéder à la procédure privée display
. L’ombre est rejeté et le compilateur résout la référence à la procédure display
de la classe de base.
Cependant, la classe dérivée thirdClass
supplémentaire déclare display
comme Public
, de sorte que le code dans callDisplay
peut y accéder.
Ombre et substitution
Ne confondez pas l’ombre et la substitution. Les deux sont utilisées lorsqu'une classe dérivée hérite d'une classe de base, et les deux redéfinissent un élément déclaré avec un autre. Mais il existe des différences significatives entre les deux. Pour une comparaison, consultez Différences entre l’ombre et la substitution.
Ombre et surcharge
Si vous ombrez le même élément de classe de base avec plusieurs éléments de votre classe dérivée, les éléments d’ombre deviennent des versions surchargées de cet élément. Pour plus d'informations, consultez Procedure Overloading.
Accès à un élément ombré
Lorsque vous accédez à un élément à partir d’une classe dérivée, vous le faites normalement via l’instance actuelle de cette classe dérivée, en qualifiant le nom d’élément avec le mot clé Me
. Si votre classe dérivée ombre l’élément dans la classe de base, vous pouvez accéder à l’élément de classe de base en le qualifiant avec le mot clé MyBase
.
Pour obtenir un exemple d’accès à un élément ombré, consultez Comment : accéder à une variable masquée par une classe dérivée.
Déclaration de la variable objet
La façon dont vous créez la variable objet peut également affecter si la classe dérivée accède à un élément d’ombre ou à l’élément ombré. L’exemple suivant crée deux objets à partir d’une classe dérivée, mais un objet est déclaré comme classe de base et l’autre comme classe dérivée.
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
Dans l’exemple précédent, la variable basObj
est déclarée comme classe de base. L’attribution d’un objet dervCls
constitue une conversion étendue et est donc valide. Toutefois, la classe de base ne peut pas accéder à la version d’ombre de la variable z
dans la classe dérivée, de sorte que le compilateur résout basObj.z
à la valeur de classe de base d’origine.