Shadowing in Visual Basic

Quando due elementi di programmazione condividono lo stesso nome, uno di essi può nascondersi, o ombreggiatura, l'altro. In tale situazione, l'elemento ombreggiato non è disponibile per riferimento; Al contrario, quando il codice usa il nome dell'elemento, il compilatore Visual Basic lo risolve nell'elemento shadowing.

Scopo

Lo scopo principale dell'ombreggiatura è proteggere la definizione dei membri della classe. La classe base potrebbe subire una modifica che crea un elemento con lo stesso nome di quello già definito. In questo caso, il modificatore forza la Shadows risoluzione dei riferimenti tramite la classe nel membro definito, anziché nel nuovo elemento della classe di base.

Tipi di ombreggiatura

Un elemento può nascondere un altro elemento in due modi diversi. L'elemento shadowing può essere dichiarato all'interno di una sottoregione dell'area contenente l'elemento ombreggiato, nel qual caso l'ombreggiatura viene eseguita tramite ambito. In alternativa, una classe derivata può ridefinire un membro di una classe di base, nel qual caso l'ombreggiatura viene eseguita tramite ereditarietà.

Shadowing attraverso l'ambito

È possibile che gli elementi di programmazione nello stesso modulo, classe o struttura abbiano lo stesso nome ma un ambito diverso. Quando due elementi vengono dichiarati in questo modo e il codice fa riferimento al nome condiviso, l'elemento con l'ambito più stretto ombreggiato l'altro elemento (l'ambito del blocco è il più stretto).

Ad esempio, un modulo può definire una Public variabile denominata tempe una routine all'interno del modulo può dichiarare anche una variabile locale denominata temp. I riferimenti a temp da all'interno della routine accedono alla variabile locale, mentre i riferimenti a temp dall'esterno della routine accedono alla Public variabile. In questo caso, la variabile temp di routine shadowsa la variabile tempdel modulo .

La figura seguente mostra due variabili, entrambe denominate temp. La variabile locale ombreggiata dalla variabile temptemp membro quando si accede dall'interno della propria routine p. Tuttavia, la MyClass parola chiave ignora l'ombreggiatura e accede alla variabile membro.

Graphic that shows shadowing through scope.

Per un esempio di ombreggiatura nell'ambito, vedere Procedura: Nascondere una variabile con lo stesso nome della variabile.

Shadowing tramite ereditarietà

Se una classe derivata ridefinisce un elemento di programmazione ereditato da una classe di base, l'elemento di ridefinizione ombreggiato dall'elemento originale. È possibile nascondere qualsiasi tipo di elemento dichiarato o set di elementi di overload con qualsiasi altro tipo. Ad esempio, una Integer variabile può nascondere una Function routine. Se si shadowa una routine con un'altra procedura, è possibile utilizzare un elenco di parametri diverso e un tipo restituito diverso.

La figura seguente mostra una classe b di base e una classe d derivata che eredita da b. La classe base definisce una routine denominata proce la classe derivata lo ombreggiatura con un'altra routine con lo stesso nome. La prima Call istruzione accede all'ombreggiatura proc nella classe derivata. Tuttavia, la MyBase parola chiave ignora l'ombreggiatura e accede alla routine shadowed nella classe di base.

Graphic diagram of shadowing through inheritance

Per un esempio di shadowing tramite ereditarietà, vedere Procedura: Nascondere una variabile con lo stesso nome della variabile e Procedura: Nascondere una variabile ereditata.

Ombreggiatura e livello di accesso

L'elemento shadowing non è sempre accessibile dal codice usando la classe derivata. Ad esempio, potrebbe essere dichiarato Private. In tal caso, l'shadowing viene sconfitto e il compilatore risolve qualsiasi riferimento allo stesso elemento che avrebbe avuto se non fosse stato eseguito alcun shadowing. Questo elemento è l'elemento accessibile il minor numero di passaggi derivatiali all'indietro dalla classe shadowing. Se l'elemento ombreggiato è una routine, la risoluzione corrisponde alla versione più vicina accessibile con lo stesso nome, elenco di parametri e tipo restituito.

Nell'esempio seguente viene illustrata una gerarchia di ereditarietà di tre classi. Ogni classe definisce una Sub routine displaye ogni classe derivata shadowsa la display routine nella relativa classe di 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  

Nell'esempio precedente, l'ombreggiatura display della classe secondClass derivata con una Private routine. Quando il modulo chiama in , il codice chiamante è esterno secondClass e pertanto non può accedere alla procedura privatadisplay.secondClassdisplaycallDisplay Shadowing viene sconfitto e il compilatore risolve il riferimento alla routine della classe display di base.

Tuttavia, l'ulteriore classe thirdClass derivata dichiara display come Public, in modo che il codice in callDisplay possa accedervi.

Ombreggiatura e override

Non confondere l'ombreggiatura con l'override. Entrambi vengono usati quando una classe derivata eredita da una classe base ed entrambi ridefiniscono un elemento dichiarato con un altro. Esistono tuttavia differenze significative tra i due. Per un confronto, vedere Differenze tra shadowing e override.

Ombreggiatura e overload

Se si shadowa lo stesso elemento della classe di base con più di un elemento nella classe derivata, gli elementi shadowing diventano versioni di overload di tale elemento. Per altre informazioni, vedere Procedure Overloading.

Accesso a un elemento ombreggiato

Quando si accede a un elemento da una classe derivata, in genere si esegue questa operazione tramite l'istanza corrente di tale classe derivata qualificando il nome dell'elemento con la Me parola chiave . Se la classe derivata shadowsa l'elemento nella classe base, è possibile accedere all'elemento della classe base qualificandolo con la MyBase parola chiave .

Per un esempio di accesso a un elemento ombreggiato, vedere Procedura: Accedere a una variabile nascosta da una classe derivata.

Dichiarazione della variabile oggetto

La modalità di creazione della variabile oggetto può influire anche sul fatto che la classe derivata acceda a un elemento shadowing o all'elemento ombreggiato. Nell'esempio seguente vengono creati due oggetti da una classe derivata, ma un oggetto viene dichiarato come classe base e l'altro come classe derivata.

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  

Nell'esempio precedente la variabile basObj viene dichiarata come classe base. L'assegnazione di un dervCls oggetto a tale oggetto costituisce una conversione più ampia ed è pertanto valida. Tuttavia, la classe base non può accedere alla versione shadowing della variabile z nella classe derivata, pertanto il compilatore viene basObj.z risolto nel valore della classe di base originale.

Vedi anche