Compartir a través de


Sombrear en Visual Basic

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 tempy 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 tempde 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.

Gráfico que muestra el sombreado mediante el ámbito.

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 procy 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.

Diagrama gráfico de sombras a través de la herencia

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 displayy 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.

Consulte también