Polymorphism in VB.net

This tutorial has been contributed by VisionForce www.visionforceweb.com. If you would like to contribute your work please contact us.

I'll start by asking a question I'm sure some of you have: what is polymorphism? Polymorphism is one of the key concepts in Object Oriented Programming. Using polymorphism enables the programmer to design software that is easily extensible which, in turn, prolongs the life of that program. The polymorphic VB.NET keywords that you will learn about in this tutorial are: MustInherit, NotInheritable, MustOverride, and NotOverridable. You will also learn to create abstract classes with these keywords, and you'll learn the key differences between abstract and concrete classes.

Part 1 - Abstract Classes

An abstract class is a class which contains very little code; but the code it contains will be used as a base for many other classes. Here is an example of an abstract class.
Public MustInherit Class CGraphicsObject

Public Overrides Function ToString() As String
Return ""
End Function

Public MustOverride Sub DrawMe()

End Class
As you can see, you won't be able to do much with an abstract class all by itself.

You may be wondering, what actually makes a class abstract? The answer is the MustInherit keyword in Public MustInherit Class CGraphicsObject. Placing the MustInherit keyword at the beginning of a class, as you might expect, forces the class to be inherited. If you tried to create an instance of this class as in the code snippet shown below, an exception would be thrown.

Programming Error:
Dim gTest As CGraphicsObject = New CGraphicsObject
gTest.DrawMe()
Any concrete classes that are derived from this CGraphicsObject class will now be required to Override the DrawMe() method; as all of the items to be drawn will be different, this is exactly what is needed. An abstract class that is derived from this CGraphicsObject class will not be required to override the DrawMe() method, but will be able to maintain the existing one. Note: If you declare even one method MustOverride, you must declare the class MustInherit.

Part 2 - Derived Classes

Now we will create a class that is derived from the CGraphicsObject class by using the Inherits keyword; see the example below:
Public MustInherit Class CPoint
	Inherits CGraphicsObject

	Private mX As Integer
	Private mY As Integer

	Public Sub New(ByVal X_value As Integer, _
		ByVal Y_value As Integer)
	
		mX = X_value
		mY = Y_value
	End Sub

	Public Property X() As Integer
		Get
			Return mX
		End Get

		Set(ByVal Value As Integer)
			mX = Value
		End Set
	End Property

	Public Property Y() As Integer
		Get
			Return mY
		End Get

		Set(ByVal Value As Integer)
			mY = Value
		End Set
	End Property

	Public Overrides Function ToString() As String
		Return Convert.ToString(X) & ", " & Convert.ToString(Y)
	End Function

End Class
This class is still abstract and this is why it is not be required to override the DrawMe() method. A point in space is invisible, so this class does not need the DrawMe() method.

Notice above that the ToString() function has been overridden and changed as necessary. For a function to be overridden, it must be declared Overridable in its base class. You will notice that in the CGraphicsObject class (the base class), the ToString() function is not declared Overridable, but Overrides. The reason for this is that all class implicity inherit the System.Object type; the System.Object type has a Public Overridable Function ToString() As String

Part 3 - Derived & Concrete Classes

You can create an instance of a concrete class. Here is an example of a concrete class, derived from the CGraphicsObject. Even though this class inherits the CPoint class, it is still a CGraphicsObject because CPoint is a CGraphicsObject.
Public NotInheritable Class CCircle
	Inherits CPoint

	Private mRadius As Double

	Public Sub New(ByVal X_val As Integer, ByVal Y_val As Integer, _
		ByVal Rad_val As Integer)
		MyBase.New(X_val, Y_val)
		mRadius = Rad_val
	End Sub

	Public Property Radius() As Double
		Get
			Return mRadius
		End Get

		Set(ByVal Value As Double)
			mRadius = Value
		End Set
	End Property

	Public Function Diameter() As Double
		Return Radius * 2
	End Function

	Public Function Area() As Double
		Return Math.PI * (Radius ^ 2)
	End Function

	Public Overrides Sub DrawMe()
		' draw the circle
	End Sub

	Public Overrides Function ToString() As String
		Return Convert.ToString(X) & ", " & Convert.ToString(Y) & _
			vbNewLine & "Radius = " & mRadius
	End Function
End Class 
You will notice many key differences here, the first being the NotInheritable keyword. Since this class is as far up the line as it goes (for now), we do not want this class to be inherited. And of course, this is what the NotInheritable keyword is for.

The second thing to notice is the call to MyBase.New(). If you need to make a call to the base class' methods (instead of the current class' methods) use MyBase. In this case, calling MyBase.New() is required. When calling MyBase.New, we also have to pass two values that are required by the CPoint class, the X and Y values.

The next thing you will notice that is different, other than the new property/functions, is that the ToString() function is changed again. This needed to be done to include the radius.

Here is another example in the derived, concrete class CRectangle.
Public NotInheritable Class CRectangle
	Inherits CPoint

	Private mWidth As Integer
	Private mHeight As Integer

	Public Sub New(ByVal X_val As Integer, ByVal Y_val As Integer, _
		ByVal Width_val As Integer, ByVal Height_val As Integer)
		MyBase.New(X_val, Y_val)
		mWidth = Width_val
		mHeight = Height_val
	End Sub

	Public Property Width() As Integer
		Get
			Return mWidth
		End Get

		Set(ByVal Value As Integer)
			mWidth = Value
		End Set
	End Property

	Public Property Height() As Integer
		Get
			Return mHeight
		End Get

		Set(ByVal Value As Integer)
			mHeight = Value
		End Set
	End Property

	Public Overrides Sub DrawMe()
		' draw the rectangle
	End Sub

	Public Overrides Function ToString() As String
		Return Convert.ToString(X) & ", " & Convert.ToString(Y) & _
			vbNewLine & Convert.ToString(Width) & "x" & _
			Convert.ToString(Height)
	End Function

End Class 
You will notice that this class is much the same as the CCircle class.

Part 4 - NotOverridable

Say you took it one step further and made a CCube class that was derived from the CRectangle class. The first thing you would have to do, of course, would be to remove the NotInheritable keyword from the CRectangle class.

Now what if the CPoint class had a special Overridable method (called SpecialMethod1) that was overridden in the CRectangle class, but you didn't want the CCube class to override CRectangle's SpecialMethod1(); what would you do? In CRectangle, you would declare its SpecialMethod1() NotOverridable as shown below.
Public NotOverridable Overrides Sub SpecialMethod1()
	' does something more interesting.
End Sub
If you try to override SpecialMethod1() in CCube, you will get a compiler error message telling you that you can't do that.

Conclusion

That concludes this tutorial on polymorphism in VB.NET. If you were unaware of or unsure of how to use polymorphism, you should be a successively better programmer as a result of this tutorial. Polymorphism is an essential in designing extensive programs.

If you have any questions or comments; something you liked/disliked, something more you wanted to learn and so on, please email webmaster@visionforceweb.com

To download the source code for this tutorial, go to:
http://www.visionforceweb.com/tutorial/GraphicsEngine.zip

© Jonathan Waller 2005; QuantumState Visual Basic