Visual Basic 中的隐藏

当两个编程元素共享同名时,其中一个元素可以隐藏或 隐藏另一个元素。 在这种情况下,阴影元素不可用供参考;相反,当代码使用元素名称时,Visual Basic 编译器会将其解析为阴影元素。

目的

阴影的主要目的是保护类成员的定义。 基类可能会发生更改,该更改创建与已定义的元素同名的元素。 如果发生这种情况,Shadows 修饰符会强制将通过你的类的引用解析为你定义的成员,而不是新的基类元素。

阴影类型

元素可以通过两种不同的方式隐藏另一个元素。 可以在包含阴影化元素的区域的子区域内声明阴影元素,在这种情况下,阴影处理是通过范围实现的。 或者派生类可以重新定义基类的成员,在这种情况下,阴影 是通过继承完成的。

通过范围实现阴影

同一模块、类或结构中的元素可以具有相同的名称,但范围不同。 以这种方式声明两个元素并且代码引用它们共享的名称时,具有较窄范围的元素将隐藏另一个元素(块范围为最窄)。

例如,模块可以定义一Public个名为temp的变量,模块中的过程可以声明一个局部变量也命名temptemp从过程内部引用访问局部变量,同时从过程外部引用temp访问变量Public。 在这种情况下,过程变量 temp 将隐藏模块变量 temp

下图显示了两个变量,两个变量都命名 temp。 从其自身过程temp中访问时,局部变量temp会遮蔽成员变量p。 但是,关键字 MyClass 会绕过阴影并访问成员变量。

此图显示如何通过范围进行隐藏。

有关通过范围实现阴影的示例,请参阅如何:隐藏与你的变量同名的变量

通过继承实现阴影。

如果派生类重新定义从基类继承的编程元素,则重新定义元素将隐藏原始元素。 可以用任何其他类型对任何类型的已声明元素或重载元素集进行阴影处理。 例如,变量 Integer 可以隐藏过程 Function 。 如果使用另一个过程隐藏过程,则可以使用不同的参数列表和不同的返回类型。

下图显示了一个基类b和一个从d中继承的派生类b。 基类定义了一个名为 proc 的过程,派生类将使用另一个同名的过程来对该过程进行阴影处理。 第一条 Call 语句将访问派生类中的阴影 proc。 但是,关键字 MyBase 会绕过阴影并访问基类中的阴影过程。

通过继承实现阴影效果的图表

有关通过继承隐藏的示例,请参阅 如何隐藏与您的变量同名的变量如何隐藏继承变量

阴影和访问级别

使用派生类的代码不一定能访问阴影元素。 例如,可以声明为 Private。 在这种情况下,遮蔽被消除,编译器会解析对同一元素的所有引用,就像没有出现过遮蔽一样。 此元素是可访问的元素,通过从阴影类向后执行最少的派生步骤即可访问。 如果阴影元素是一个过程,则解析为最接近的可访问版本,其名称、参数列表和返回类型相同。

以下示例显示了三个类的继承层次结构。 每个类都定义了一个 Sub 过程 display,每个派生类在其基类中隐藏 display 该过程。

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  

在前面的示例中,派生类 secondClass 通过 display 过程对 Private 进行阴影处理。 当模块 callDisplaydisplay 中调用 secondClass 时,调用代码位于 secondClass 外部,因此无法访问私有 display 过程。 阴影已失效,编译器将引用解析为基类 display 过程。

但是,进一步派生的类 thirdClass 声明 displayPublic,因此代码在 callDisplay 中可以访问它。

阴影和重写。

不要将阴影与重写混淆。 当派生类继承自基类时,这两者都用于重新定义一个声明的元素和另一个元素。 但两者之间存在重大差异。 有关比较,请参阅阴影和重写之间的差异

阴影和重载

如果在派生类中对具有多个元素的同一个基类元素进行阴影处理,则阴影元素将成为该元素的重载版本。 有关详细信息,请参阅 过程重载

访问阴影元素

访问派生类的元素时,通常通过该派生类的当前实例,并使用 Me 关键字限定元素名称。 如果派生类对基类中的元素产生阴影,则可以通过使用 MyBase 关键字限定基类元素来访问基类元素。

有关访问阴影元素的示例,请参阅 “如何:访问派生类隐藏的变量”。

对象变量的声明

创建对象变量的方式还会影响派生类是访问阴影元素还是访问阴影化元素。 以下示例从派生类创建两个对象,但一个对象声明为基类,另一个对象声明为派生类。

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  

在前面的示例中,变量 basObj 声明为基类。 将对象 dervCls 分配给它构成了一种扩大转换,这是有效的。 但是,基类无法访问派生类中变量 z 的阴影版本,因此编译器解析 basObj.z 为原始基类值。

另请参阅