Partager via


Ombre dans Visual Basic

Lorsque deux éléments de programmation partagent le même nom, l’un d’entre eux peut masquer ou cacher l’autre. Dans ce cas, l’é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’élément d’ombre.

Objectif

L’objectif principal du masquage 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 que celui que vous avez déjà défini. Dans ce cas, le Shadows modificateur force les références à travers votre classe à être résolues vers le membre que vous avez défini, plutôt qu'au nouvel élément de la classe de base.

Types de masquage

Un élément peut ombrer un autre élément de deux façons différentes. L’élément masquant peut être déclaré à l’intérieur d’une sous-région de la région contenant l’élément masqué, auquel cas le masquage est effectué par é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.

Masquage par é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 étroite ombre l’autre élément (l’étendue de bloc est la plus étroite).

Par exemple, un module peut définir une Public variable 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 depuis la procédure accèdent à la variable locale temp, tandis que les références à Public depuis l’extérieur de la procédure accèdent à la variable . Dans ce cas, la variable de procédure temp masque la variable de module temp.

L’illustration suivante montre deux variables nommées temp. La variable temp locale ombre la variable temp membre lorsqu’elle est accessible à partir de sa propre procédure p. Toutefois, le MyClass mot clé contourne l’ombre et accède à la variable membre.

Graphique montrant l’ombre à travers le champ de vision.

Pour obtenir un exemple d’ombrage par la portée, consultez Guide pratique pour masquer une variable portant le même nom que votre variable.

Masquage par 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 redéfining 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 Integer variable peut ombrer une Function procédure. 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 b de base et une classe d dérivée qui hérite de b. La classe de base définit une procédure nommée proc, et la classe dérivée la masque avec une autre procédure du même nom. La première instruction Call accède au masquage proc dans la classe dérivée. Toutefois, le mot clé MyBase contourne le masquage et accède à la procédure masquée dans la classe de base.

Diagramme graphique de l’ombre par héritage

Pour obtenir un exemple d’ombre par héritage, consultez Guide pratique pour 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, le masquage est annulé et le compilateur résout toute référence au même élément que s'il n'y avait pas eu de masquage. Cet élément est l’élément accessible le plus proche en remontant le moins d’étapes d’héritage depuis la classe masquante. Si l’élément ombré est une procédure, la résolution est à la version la plus proche accessible portant le même nom, la liste de paramètres et le type de retour.

L’exemple suivant montre une hiérarchie d’héritage de trois classes. Chaque classe définit une Sub procédure displayet chaque classe dérivée ombre la display procédure 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 secondClass dérivée masque 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. Le masquage est contourné et le compilateur résout la référence vers la procédure de la classe de base display.

Toutefois, la classe thirdClass dérivée supplémentaire déclare display en tant que Public, permettant ainsi au code dans callDisplay d'y accéder.

Masquage et substitution

Ne confondez pas masquage et substitution. Les deux sont utilisés lorsqu’une classe dérivée hérite d’une classe de base et redéfinissent un élément déclaré avec un autre. Mais il y a des différences significatives entre les deux. Pour une comparaison, consultez Différences entre le masquage et la substitution.

Masquage 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 Surcharge de procédure.

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 qualifier le nom d’élément avec le Me mot clé. 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 qualifier avec le MyBase mot clé.

Pour obtenir un exemple d’accès à un élément ombré, consultez Guide pratique pour 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. Affecter un objet dervCls constitue une conversion étendue et est donc valide. Toutefois, la classe de base ne peut pas accéder à la version masquée de la variable z dans la classe dérivée, donc le compilateur résout basObj.z à la valeur originale de la classe de base.

Voir aussi