Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Cuando dos elementos de programación comparten el mismo nombre, uno de ellos puede ocultar, o sombra, el otro. En tal situación, el elemento sombreado no está disponible para referencia; en su lugar, cuando el código usa el nombre del elemento, el compilador de Visual Basic lo resuelve en el elemento de sombreado.
Propósito
El objetivo principal del sombreado es proteger la definición de los miembros de la clase. La clase base puede sufrir un cambio que cree un elemento con el mismo nombre que el que ya haya definido. Si esto sucede, el modificador Shadows
obliga a que las referencias de su clase se resuelvan en el miembro que usted definió, en lugar de en el nuevo elemento de clase base.
Tipos de sombreado
Un elemento puede sombrear otro elemento de dos maneras diferentes. El elemento de sombreado se puede declarar dentro de una subdivisión de la región que contiene el elemento sombreado, en cuyo caso el sombreado se realiza a través del ámbito. O bien, una clase derivada puede redefinir un miembro de una clase base, en cuyo caso la sombra se realiza a través de la herencia.
Sombreado mediante el ámbito
Es posible que los elementos de programación del mismo módulo, clase o estructura tengan el mismo nombre pero un ámbito diferente. Cuando se declaran dos elementos de esta manera y el código hace referencia al nombre que comparten, el elemento con el ámbito más estrecho sombrea el otro elemento (el ámbito de bloque es el más estrecho).
Por ejemplo, un módulo puede definir una Public
variable denominada temp
y un procedimiento dentro del módulo puede declarar una variable local también denominada temp
. Las referencias a temp
desde dentro del procedimiento acceden a la variable local, mientras que las referencias a temp
desde fuera del procedimiento acceden a la variable Public
. En este caso, la variable temp
de procedimiento sombrea la variable temp
de módulo .
En la ilustración siguiente se muestran dos variables, ambas denominadas temp
. La variable local temp
sombrea la variable miembro temp
cuando se accede desde su propio procedimiento p
. Sin embargo, la palabra clave MyClass
omite el sombreado y accede a la variable de miembro.
Para obtener un ejemplo de sombreado mediante el ámbito, consulte Cómo: Ocultar una variable con el mismo nombre que su variable.
Sombreado mediante herencia
Si una clase derivada vuelve a definir un elemento de programación heredado de una clase base, el elemento redefinir sombrea el elemento original. Puede sombrear cualquier tipo de elemento declarado, o conjunto de elementos sobrecargados, con cualquier otro tipo. Por ejemplo, una Integer
variable puede sombrear un Function
procedimiento. Si sombrea un procedimiento con otro procedimiento, puede usar una lista de parámetros diferente y otro tipo de valor devuelto.
En la ilustración siguiente se muestra una clase b
base y una clase d
derivada que hereda de b
. La clase base define un procedimiento denominado proc
y la clase derivada lo sombrea con otro procedimiento del mismo nombre. La primera instrucción Call
accede al procedimiento proc
que realiza el sombreado en la clase derivada. Sin embargo, la palabra clave MyBase
omite este procedimiento y accede al procedimiento sombreado en la clase base.
Para obtener un ejemplo de sombreado a través de la herencia, consulte Cómo: Ocultar una variable con el mismo nombre que otra variable suya y Cómo: Ocultar una variable heredada.
Sombra y nivel de acceso
El elemento de sombreado no siempre es accesible desde el código mediante la clase derivada. Por ejemplo, podría declararse Private
. En tal caso, el sombreado se anula y el compilador resuelve cualquier referencia al mismo elemento como lo haría si no existiese el sombreado. Este elemento es el elemento accesible con menos pasos de derivación hacia atrás desde la clase que realiza el sombreado. Si el elemento sombreado es un procedimiento, la resolución es a la versión accesible más cercana con el mismo nombre, lista de parámetros y tipo de valor devuelto.
En el ejemplo siguiente se muestra una jerarquía de herencia de tres clases. Cada clase define un Sub
procedimiento display
y cada clase derivada sombrea el display
procedimiento en su clase 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
En el ejemplo anterior, la clase derivada secondClass
sombrea display
por un procedimiento Private
. Cuando el módulo callDisplay
llama a display
en secondClass
, el código de llamada está fuera secondClass
y, por tanto, no puede acceder al procedimiento privado display
. El sombreado se anula y el compilador resuelve la referencia al procedimiento display
de la clase base.
Sin embargo, la clase thirdClass
derivada adicional declara display
como Public
, por lo que el código de callDisplay
puede acceder a él.
Sombreado y reemplazos
No confunda el sombreado con el reemplazo. Ambos se usan cuando una clase derivada hereda de una clase base y ambas vuelven a definir un elemento declarado con otro. Pero hay diferencias significativas entre los dos. Para ver una comparación, consulte Diferencias entre sombrear y reemplazar.
Sombreado y sobrecarga.
Si oscurece el mismo elemento de clase base con más de un elemento en su clase derivada, los elementos sombreados se convierten en versiones sobrecargadas de ese elemento. Para obtener más información, vea Sobrecarga de procedimientos.
Acceso a un elemento sombreado
Cuando se accede a un elemento de una clase derivada, normalmente lo hace a través de la instancia actual de esa clase derivada, calificando el nombre del elemento con la Me
palabra clave . Si la clase derivada sombrea el elemento de la clase base, puede acceder al elemento de clase base si lo califica con la MyBase
palabra clave .
Para obtener un ejemplo de acceso a un elemento sombreado, vea Cómo: Obtener acceso a una variable oculta por una clase derivada.
Declaración de la variable de objeto
La forma de crear la variable de objeto también puede afectar a si la clase derivada tiene acceso a un elemento que oculta o al elemento ocultado. En el ejemplo siguiente se crean dos objetos a partir de una clase derivada, pero un objeto se declara como la clase base y la otra como clase derivada.
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
En el ejemplo anterior, la variable basObj
se declara como la clase base. Asignar un dervCls
objeto a él constituye una conversión de ampliación y, por tanto, es válida. Sin embargo, la clase base no puede acceder a la versión de enmascaramiento de la variable z
en la clase derivada, por lo que el compilador resuelve basObj.z
al valor original de la clase base.