A derived type shadows the name of an inherited type member by
redeclaring it. Shadowing a name does not remove the inherited type
members with that name; it merely makes all of the inherited type
members with that name unavailable in the derived class. The shadowing
declaration may be any type of entity.
Entities than can be overloaded can choose one of two forms of shadowing. Shadowing by name is specified using the Shadows keyword. An entity that shadows by name hides everything by that name in the base class, including all overloads. Shadowing by name and signature is specified using the Overloads
keyword. An entity that shadows by name and signature hides everything
by that name with the same signature as the entity. For example:
Imports System
Class Base
Sub F()
End Sub
Sub F(ByVal i As Integer)
End Sub
Sub G()
End Sub
Sub G(ByVal i As Integer)
End Sub
End Class
Class Derived
Inherits Base
' Only hides F(Integer).
Overloads Sub F(ByVal i As Integer)
End Sub
' Hides G() and G(Integer).
Shadows Sub G(ByVal i As Integer)
End Sub
End Class
Module Test
Sub Main()
Dim x As Derived = New Derived()
x.F() ' Calls Base.F().
x.G() ' Error: No such method.
End Sub
End Module
A shadowing method or property that does not specify Shadows or Overloads assumes Shadows. If one member of a set of overloaded entities specifies the Shadows or Overloads keyword, they all must specify it. The Shadows and Overloads keywords cannot be specified at the same time.
It
is valid to shadow the name of a type member that has been
multiply-inherited through interface inheritance (and which is thereby
unavailable), thus making the name available in the derived interface.
For example:
Interface ILeft
Sub F()
End Interface
Interface IRight
Sub F()
End Interface
Interface ILeftRight
Inherits ILeft, IRight
Shadows Sub F()
End Interface
Module Test
Sub G(ByVal i As ILeftRight)
i.F() ' Calls ILeftRight.F.
CType(i, ILeft).F() ' Calls ILeft.F.
CType(i, IRight).F() ' Calls IRight.F.
End Sub
End Module
Because methods are allowed to shadow inherited methods, it is possible for a class to contain several Overridable
methods with the same signature. This does not present an ambiguity
problem, since only the most-derived method is visible. In the
following example, the C
and D
classes contain two Overridable methods with the same signature:
Imports System
Class A
Public Overridable Sub F()
Console.WriteLine("A.F")
End Sub
End Class
Class B
Inherits A
Public Overrides Sub F()
Console.WriteLine("B.F")
End Sub
End Class
Class C
Inherits B
Public Shadows Overridable Sub F()
Console.WriteLine("C.F")
End Sub
End Class
Class D
Inherits C
Public Overrides Sub F()
Console.WriteLine("D.F")
End Sub
End Class
Module Test
Sub Main()
Dim d As New D()
Dim a As A = d
Dim b As B = d
Dim c As C = d
a.F()
b.F()
c.F()
d.F()
End Sub
End Module
There are two Overridable methods here: one introduced by class A
and the one introduced by class C
. The method introduced by class C
hides the method inherited from class A
. Thus, the Overrides declaration in class D
overrides the method introduced by class C
, and it is not possible for class D
to override the method introduced by class A
. The example produces the output:
It is possible to invoke the hidden Overridable method by accessing an instance of class D
through a less-derived type in which the method is not hidden.
It is not valid to shadow a MustOverride method, because in most cases this would make the class unusable. For example:
MustInherit Class Base
Public MustOverride Sub F()
End Class
MustInherit Class Derived
Inherits Base
Public Shadows Sub F()
End Sub
End Class
Class MoreDerived
Inherits Derived
' Error: MustOverride method Base.F is not overridden.
End Class
In this case, the class MoreDerived
is required to override the MustOverride method Base.F
, but because the class Derived
shadows Base.F
, this is not possible. There is no way to declare a valid descendent of Derived
.
In
contrast to shadowing a name from an outer scope, shadowing an
accessible name from an inherited scope causes a warning to be
reported, as in the following example:
Class Base
Public Sub F()
End Sub
Private Sub G()
End Sub
End Class
Class Derived
Inherits Base
Public Sub F() ' Warning: shadowing an inherited name.
End Sub
Public Sub G() ' No warning, Base.G is not accessible here.
End Sub
End Class
The declaration of method F
in class Derived
causes a warning to be reported. Shadowing an inherited name is
specifically not an error, since that would preclude separate evolution
of base classes. For example, the above situation might have come about
because a later version of class Base
introduced a method F
that was not present in an earlier version of the class. Had the above situation been an error, any change made to a base class in a separately versioned class library could potentially cause derived classes to become invalid.
The warning caused by shadowing an inherited name can be eliminated through use of the Shadows or Overloads modifier:
Class Base
Public Sub F()
End Sub
End Class
Class Derived
Inherits Base
Public Shadows Sub F() 'OK.
End Sub
End Class
The Shadows modifier indicates the intention to shadow the inherited member. It is not an error to specify the Shadows or Overloads modifier if there is no type member name to shadow.
A declaration of a new member shadows an inherited member only within the scope of the new member, as in the following example:
Class Base
Public Shared Sub F()
End Sub
End Class
Class Derived
Inherits Base
Private Shared Shadows Sub F() ' Shadows Base.F in class Derived only.
End Sub
End Class
Class MoreDerived
Inherits Derived
Shared Sub G()
F() ' Invokes Base.F.
End Sub
End Class
In the example above, the declaration of method F
in class Derived
shadows the method F
that was inherited from class Base
, but since the new method F
in class Derived
has Private access, its scope does not extend to class MoreDerived
. Thus, the call F()
in MoreDerived.G
is valid and will invoke Base.F
.
In the case of overloaded type members, the entire set of overloaded
type members is treated as if they all had the most permissive access
for the purposes of shadowing.
Class Base
Public Sub F()
End Sub
End Class
Class Derived
Inherits Base
Private Shadows Sub F()
End Sub
Public Shadows Sub F(ByVal i As Integer)
End Sub
End Class
Class MoreDerived
Inherits Derived
Public Sub G()
F() ' Error. No accessible member with this signature.
End Sub
End Class
In this example, even though the declaration of F()
in Derived
is declared with Private access, the overloaded F(Integer)
is declared with Public access. Therefore, for the purpose of shadowing, the name F
in Derived
is treated as if it was Public, so both methods shadow F
in Base
.