Sombreamento no Visual Basic

Quando dois elementos de programação compartilham o mesmo nome, um deles pode esconder, ou sombrear, o outro. Em tal situação, o elemento sombreado não está disponível para referência; em vez disso, quando seu código usa o nome do elemento, o compilador do Visual Basic o resolve para o elemento de sombreamento.

Propósito

O principal objetivo do shadowing é proteger a definição dos membros da sua classe. A classe base pode sofrer uma alteração que cria um elemento com o mesmo nome que um que você já definiu. Se isso acontecer, o modificador forçará as Shadows referências através de sua classe a serem resolvidas para o membro que você definiu, em vez de para o novo elemento de classe base.

Tipos de sombreamento

Um elemento pode sombrear outro elemento de duas maneiras diferentes. O elemento de sombreamento pode ser declarado dentro de uma sub-região da região que contém o elemento sombreado, caso em que o sombreamento é realizado através do escopo. Ou uma classe derivada pode redefinir um membro de uma classe base, caso em que o sombreamento é feito por herança.

Sombreamento através do escopo

É possível que elementos de programação no mesmo módulo, classe ou estrutura tenham o mesmo nome, mas escopo diferente. Quando dois elementos são declarados dessa maneira e o código se refere ao nome que eles compartilham, o elemento com o escopo mais estreito sombreia o outro elemento (o escopo do bloco é o mais estreito).

Por exemplo, um módulo pode definir uma Public variável chamada temp, e um procedimento dentro do módulo pode declarar uma variável local também chamada temp. As referências de temp dentro do procedimento acessam a variável local, enquanto as referências de temp fora do procedimento acessam a Public variável. Neste caso, a variável temp procedure sombreia a variável tempmodule .

A ilustração a seguir mostra duas variáveis, ambas denominadas temp. A variável temp local sombreia a variável temp membro quando acessada de dentro de seu próprio procedimento p. No entanto, a MyClass palavra-chave ignora o sombreamento e acessa a variável membro.

Graphic that shows shadowing through scope.

Para obter um exemplo de sombreamento pelo escopo, consulte Como ocultar uma variável com o mesmo nome da variável.

Sombreamento através da herança

Se uma classe derivada redefine um elemento de programação herdado de uma classe base, o elemento de redefinição sombreia o elemento original. Você pode sombrear qualquer tipo de elemento declarado, ou conjunto de elementos sobrecarregados, com qualquer outro tipo. Por exemplo, uma Integer variável pode sombrear um Function procedimento. Se você sombrear um procedimento com outro procedimento, poderá usar uma lista de parâmetros diferente e um tipo de retorno diferente.

A ilustração a seguir mostra uma classe b base e uma classe d derivada que herda de b. A classe base define um procedimento chamado proc, e a classe derivada o sombreia com outro procedimento do mesmo nome. A primeira Call instrução acessa o sombreamento proc na classe derivada. No entanto, a MyBase palavra-chave ignora o sombreamento e acessa o procedimento sombreado na classe base.

Graphic diagram of shadowing through inheritance

Para obter um exemplo de sombreamento através da herança, consulte Como ocultar uma variável com o mesmo nome da variável e Como ocultar uma variável herdada.

Sombreamento e Nível de Acesso

O elemento de sombreamento nem sempre é acessível a partir do código usando a classe derivada. Por exemplo, pode ser declarado Private. Nesse caso, o sombreamento é derrotado e o compilador resolve qualquer referência ao mesmo elemento que teria se não houvesse sombreamento. Este elemento é o elemento acessível o menor número de passos derivacionais para trás da classe de sombreamento. Se o elemento sombreado for um procedimento, a resolução será para a versão acessível mais próxima com o mesmo nome, lista de parâmetros e tipo de retorno.

O exemplo a seguir mostra uma hierarquia de herança de três classes. Cada classe define um Sub procedimento displaye cada classe derivada sombreia o display procedimento em sua classe 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  

No exemplo anterior, a classe secondClass derivada sombreia display com um Private procedimento. Quando o módulo callDisplay chamasecondClassdisplay, o código de chamada está fora secondClass e, portanto, não pode acessar o procedimento privadodisplay. O sombreamento é derrotado e o compilador resolve a referência ao procedimento de classe display base.

No entanto, a classe thirdClass display derivada declara como Public, para que o código em callDisplay possa acessá-la.

Sombreamento e sobreposição

Não confunda sombreamento com substituição. Ambos são usados quando uma classe derivada herda de uma classe base e ambos redefinem um elemento declarado com outro. Mas há diferenças significativas entre os dois. Para uma comparação, consulte Diferenças entre sombreamento e substituição.

Sombreamento e sobrecarga

Se você sombrear o mesmo elemento de classe base com mais de um elemento em sua classe derivada, os elementos de sombreamento se tornarão versões sobrecarregadas desse elemento. Para obter mais informações, consulte Sobrecarga de procedimento.

Acessando um elemento sombreado

Quando você acessa um elemento de uma classe derivada, normalmente o faz por meio da instância atual dessa classe derivada, qualificando o nome do elemento com a Me palavra-chave. Se sua classe derivada sombrear o elemento na classe base, você poderá acessar o elemento de classe base qualificando-o com a MyBase palavra-chave.

Para obter um exemplo de acesso a um elemento sombreado, consulte Como acessar uma variável oculta por uma classe derivada.

Declaração da variável de objeto

A forma como você cria a variável de objeto também pode afetar se a classe derivada acessa um elemento de sombreamento ou o elemento sombreado. O exemplo a seguir cria dois objetos de uma classe derivada, mas um objeto é declarado como a classe base e o outro como a classe 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  

No exemplo anterior, a variável basObj é declarada como a classe base. A atribuição de um dervCls objeto a ele constitui uma conversão crescente e, portanto, é válida. No entanto, a classe base não pode acessar a versão de sombreamento da variável z na classe derivada, portanto, o compilador resolve basObj.z para o valor da classe base original.

Consulte também