This article gives you an in-depth understanding of how to use "Shadows" in Visual Basic 2005. You will also see how "overloads" can replace "shadows" in certain situations.
The entire source code for this article is available in the form of a downloadable zip file. The solution was developed using Microsoft Visual Studio 2005 Professional Edition on Microsoft Windows Server 2003 Enterprise Edition. I didn't really test it in any other environment. I request that you post in the discussion area if you have any problems in execution.
A simple demonstration of "Shadows" in Visual Basic 2005
In my previous article, I discussed overloading and overriding in Visual Basic 2005. Now, I shall discuss Shadowing in Visual Basic 2005. Before going into the explanation, let us go through the following sample:
Public Class Parent
Public x As Integer = 10
End Class
Public Class Child
Inherits Parent
Public x As Integer = 20
End Class
I defined two classes, "Parent" and "Child," where "Child" gets inherited from "Parent." If I create an object (instance) with respect to "Parent" and access the field (x) as follows, there is no doubt that it displays "10."
Dim obj As New Parent
MessageBox.Show(obj.x)
However, if I create an object with respect to "Child" and access the field (x) as follows, the confusion starts:
Dim obj As New Child
MessageBox.Show(obj.x)
The class "Child" is equipped with the same field (x) twice -- one inherited from "Parent" and one of its own. If such a situation occurs, the field in the "child" shadows the field in "parent." In other words, the child member temporarily hides the parent member and activates its own. This is called shadowing.
Even though we don't specify the word "shadows," the editor gives a warning message and defaults to "Shadows." The rewritten field for the above is as follows:
Public Shadows x As Integer = 20 'default is shadows even if it is not defined
Public Shadows x As Integer = 20 'default is shadows even if it is not defined
End Class
To test the above classes, I created two objects and accessed the fields as follows:
Dim objParent As New Parent
Dim objChild As New Child
MessageBox.Show("From Parent: " & objParent.x)
MessageBox.Show("From Child: " & objChild.x)
From the above, the first message gives "10" and the second gives "20."
Let us consider that I would like to access the parent member from the child object. It can be done using the following style of code:
Dim objChild As New Child
Dim RefParent As Parent = objChild
MessageBox.Show("From child with Parent Ref: " & RefParent.x)
In the above code "objChild" is a full-fledged instance and "RefParent" is simply a reference to another memory location (no new memory gets allocated for this). When inheritance is implemented, a child instance can be assigned to a parent reference; if necessary we can even type-cast it.
When we try to access a shadowed member in the child through a parent reference, the program doesn't consider shadowing any more. It concentrates only on parent members and thus the result would be "10."
In previous sections, we concentrated only on fields. Now I shall extend the same discussion to "properties" with "shadows" in this section.
Let us consider the following classes:
Public Class Parent
Private _x As Integer
Public Property X() As Integer
Get
Return _x
End Get
Set(ByVal value As Integer)
_x = value
End Set
End Property
End Class
Public Class Child
Inherits Parent
Private _x As Integer
Public Shadows Property X() As Integer
Get
Return _x
End Get
Set(ByVal value As Integer)
_x = value
End Set
End Property
End Class
In the above classes, I declared the same two members in each (one field and one property). You should clearly observe that the field "_x" is not defined with "shadows" even though it is available in both. Neither has it given a warning. This is because the field is mentioned with "private." When a member is defined as "private," it is invisible outside the class and thus doesn't require any "overrides" or "shadows."
Unlike the field "_x," the property "X" is defined as "public" and is identically declared in both; thus it requires "shadows."
We can test the above classes using the following style of code:
Dim objParent As New Parent
objParent.X = 10
Dim objChild As New Child
objChild.X = 20
MessageBox.Show("From parent: " & objParent.X)
MessageBox.Show("From child: " & objChild.X)
It displays 10 and 20 as expected. We can even modify the value of the parent member from the child instance as shown below:
Dim RefParent As Parent = objChild
RefParent.X = 30
MessageBox.Show("From parent: " & objParent.X)
MessageBox.Show("From child: " & objChild.X)
MessageBox.Show("From child with parent ref: " & RefParent.X)
In previous sections, I discussed both fields and properties using "shadows." "Shadows" are not limited to "Fields" and "Properties;" they can also be used for "methods." Now I'm extending the discussion to "methods."
Consider the following code before we proceed:
Public Class Parent
Public Sub DispMsg()
MessageBox.Show("From Parent")
End Sub
End Class
Public Class Child
Inherits Parent
Public Shadows Sub DispMsg()
MessageBox.Show("From child")
End Sub
End Class
In the above two classes, there exists the same method, "DispMsg," with the same signature (which may have different implementations). Thus we need "shadows."
We can test the above classes using the following style of code:
Dim objParent As New Parent
Dim objChild As New Child
objParent.DispMsg()
objChild.DispMsg()
And finally, using a parent reference, we can test as follows (which displays "From Parent"):
Dim RefParent As Parent = objChild
RefParent.DispMsg()
We can even access a parent member without creating a separate reference variable as follows:
CType(objChild, Parent).DispMsg()
The above applies even to shadowed "fields" and "properties."
This is a different situation when compared to any of the previous sections. I would like to have overloaded methods in the parent and "shadow" a method in the child.
Let us go through the following code first:
Public Class Parent
Public Sub DispMsg()
MessageBox.Show("From Parent")
End Sub
Public Sub DispMsg(ByVal Msg As String)
MessageBox.Show(Msg)
End Sub
End Class
Public Class Child
Inherits Parent
Public Shadows Sub DispMsg()
MessageBox.Show("From child")
End Sub
End Class
In the "Parent" class I defined two overloaded methods named "DispMsg" (one with a parameter and the other without a parameter). In the "Child" class I am shadowing only the method that does not have a parameter.
Let us try to access the members with the following testing statements:
Dim objParent As New Parent
objParent.DispMsg()
objParent.DispMsg("Custom msg for parent")
No problem, the above works as the parent has both methods. Let us proceed to the following:
Dim objChild As New Child
Dim RefParent As Parent = objChild
objChild.DispMsg()
'objChild.DispMsg("Custom msg for child") 'wont work with shadow
RefParent.DispMsg()
RefParent.DispMsg("Custom msg from ref object")
From the above, you can understand that we can still access both parent methods from a parent reference. But the child can access only the shadowed method. In other words, the keyword "shadows" completely hides based on name and not on signature.
In the previous section, we observed that the keyword "shadows" completely hides based on name and not on signature. But what if we want to access all the methods from the parent through the child (without shadowing)? It is possible with "overloads!"
Let us redefine our classes as follows:
Public Class Parent
Public Sub DispMsg()
MessageBox.Show("From Parent")
End Sub
Public Sub DispMsg(ByVal Msg As String)
MessageBox.Show(Msg)
End Sub
End Class
Public Class Child2
Inherits Parent
Public Overloads Sub DispMsg()
MessageBox.Show("From child2")
End Sub
End Class
If you observe the "Child2," class, I replaced "shadows" with "overloads." This hides based on signature and not on name.
Let us test the classes using the following statements:
Dim objParent As New Parent
objParent.DispMsg()
objParent.DispMsg("Custom msg for parent")
We should not have any problem with the above, and indeed, it works successfully. Now let us proceed with the child object as follows:
Dim objChild As New Child2
Dim RefParent As Parent = objChild
objChild.DispMsg()
objChild.DispMsg("Custom msg for child2") 'works with overload
RefParent.DispMsg()
RefParent.DispMsg("Custom msg from ref object")
Now you can see that we are able to access all of the methods in the child and also in the parent (using a parent reference).
My previous article gave a good in depth understanding of "overrides" and "overloads" in Visual Basic 2005. This article completely discussed "shadows" together with "overloads" in Visual Basic 2005. In my next article, you will find information on "abstract" classes and "interfaces" together defining "polymorphism" using Visual Basic 2005.
I hope you enjoyed the article and any suggestions, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com