Condividi tramite


Ombreggiatura in Visual Basic

Quando due elementi di programmazione condividono lo stesso nome, uno di essi può nascondere, o oscurare, l'altro. In tale situazione, l'elemento ombreggiato non è disponibile per riferimento; Quando invece il codice usa il nome dell'elemento, il compilatore visual Basic lo risolve nell'elemento shadowing.

Scopo

Lo scopo principale del shadowing è 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 Shadows forza la risoluzione dei riferimenti tramite la tua classe al membro che hai definito, anziché al nuovo elemento della classe di base.

Tipi di ombreggiatura

Un elemento può nascondere un altro elemento in due modi diversi. L'elemento di mascheramento può essere dichiarato all'interno di un'area secondaria dell'area contenente l'elemento mascherato, in tal caso il mascheramento viene eseguito tramite visibilità. In alternativa, una classe derivata può ridefinire un membro di una classe di base, nel qual caso l'ombreggiatura viene eseguita tramite ereditarietà.

Ombreggiatura attraverso lo scope

È 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ù ristretto oscura l'altro elemento (l'ambito di un blocco è il più ristretto).

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

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

Immagine che mostra l'ombreggiatura attraverso il mirino.

Per un esempio di shadowing in scope, vedere Procedura: Nascondere una variabile con lo stesso nome della tua variabile.

Shadowing tramite ereditarietà

Se una classe derivata ridefinisce un elemento di programmazione ereditato da una classe base, l'elemento che definisce ombreggiate l'elemento originale. È possibile oscurare qualsiasi tipo di elemento dichiarato o insieme di elementi sovraccaricati con qualsiasi altro tipo. Ad esempio, una Integer variabile può nascondere una Function routine. Se si oscura una procedura con un'altra procedura, è possibile utilizzare un elenco di parametri diverso e un tipo di ritorno diverso.

La figura seguente illustra una classe b base e una classe d derivata che eredita da b. La classe base definisce una procedura denominata proc e la classe derivata la nasconde con un'altra procedura 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 procedura ombreggiata nella classe di base.

Diagramma grafico del mascheramento tramite ereditarietà

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

Monitoraggio e livello di accesso

L'elemento di ombreggiatura non è sempre accessibile dal codice utilizzando la classe derivata. Ad esempio, potrebbe essere dichiarato Private. In questo caso, l'ombreggiatura viene annullata e il compilatore risolve qualsiasi riferimento allo stesso elemento che avrebbe avuto se non ci fosse stata alcuna ombreggiatura. Questo elemento è l'elemento accessibile con il minor numero di passaggi derivativi a ritroso dalla classe che effettua 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 procedura display e ogni classe derivata nasconde la display procedura nella sua 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, la classe derivata secondClass oscura display con una procedura Private. Quando il modulo callDisplay chiama display in secondClass, il codice chiamante è esterno a secondClass e pertanto non può accedere alla procedura privata display. 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. Ma ci sono differenze significative tra i due. Per un confronto, vedere Differenze tra mascheramento e sovrascrittura.

Ombreggiatura e sovraccarico

Se si nasconde lo stesso elemento della classe base con più di un elemento nella classe derivata, gli elementi che lo nascondono diventano versioni sovraccariche di tale elemento. Per altre informazioni, vedere Sovraccarico delle procedure.

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 oscura l'elemento nella classe base, è possibile accedere all'elemento della classe di base qualificandolo con la parola chiave MyBase.

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

Dichiarazione della variabile oggetto

Il modo in cui si crea la variabile oggetto può influenzare anche se la classe derivata accede a un elemento di nascondimento o all'elemento nascosto. Nell'esempio seguente vengono creati due oggetti da una classe derivata, ma un oggetto viene dichiarato come classe di 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 verso un tipo di dati più ampio ed è pertanto valida. Tuttavia, la classe base non può accedere alla versione nascosta della variabile z nella classe derivata, quindi il compilatore risolve basObj.z al valore originale della classe di base.

Vedere anche