Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
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 temp
e una routine all'interno del modulo può dichiarare una variabile locale denominata temp
anche . 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.
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.
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.