The Overloads, Overrides, and Shadows Keywords in VB.NET – Part 3
(From an article I originally wrote in 2004)
Part 3
Note:
This series covers advanced topics and is not intended to be an exhaustive treatment of the subjects discussed. My intention is to provide the reader with a better understanding of the Overloads, Overrides, and Shadows keywords. Where necessary, I will refer the reader to other sources for more details. If you’re a VB.Net programmer who writes software components intended for use by other programmers or applications that can be extended by other programmers, or if you use third party components or extend components written by others, you will certainly want to become more familiar with these keywords as they will allow you to leverage more of the power and flexibility built into an object oriented language like VB.NET.
This series is applicable to VB.NET programmers only. C# provides it’s own flavor of support for member hiding (shadowing), virtual functions, and overloading. And since there are significant differences in the C# implementation, here we’re talking only VB.NET.
Also, in these articles I use the word method to mean any procedure in VB.NET (i.e., Subs, Functions, and Property procedures).
In the last installment of this article we discussed overloading and the Overloads keyword. In this installment we discuss overriding and the Overrides keyword.
A word of warning is in order here: The topics discussed in this installment involve inheritance, virtual functions, and polymorphism. These are some of the most complex interrelated concepts you will find in an object oriented language and I reiterate that they cannot be thoroughly discussed within the confines of a short article such as this. So I will cover them only enough to explain the use of the Overrides keyword and you will want to pay attention, especially if you are new to these concepts.
Also, if you’re not familiar with the concept of Inheritance, read about it here and then return to this article.
Virtual Functions
Before you can understand the use of the Overrides keyword, you have to understand the concept of Virtual Functions. The term “virtual function” is often encountered in the C++ language, not in VB.Net, but it means the same thing when discussed within the context of any object oriented language and it’s implementation of inheritance. I mention it here only because it does a good job of placing a name to the concept of dynamic binding of methods in object oriented languages.
A virtual function is a method in a base class that can be redefined in a derived class. The actual binding between the call to the method and the method’s implementation does not occur until run time.
It is important to understand those last two sentences, but if they are confusing to you, don’t worry I’ll elaborate shortly.
In VB.NET you can designate a method to be virtual by declaring it in the base class with the Overridable keyword. That keyword means that a method can be redefined (referred to as overridden in VB.Net parlance) if the designer of a derived class wishes to do so. From this point forward in this article, when I refer to a virtual function I will use the term Overridable or Overridden, so I may say “overridable property,” or “overridable function,” or “overridden property,” etc.
In the following example we have a base class named Animal and we want to provide an Overridable property for the number of legs that the animal has. We decide that most animals will have 4 legs so we use that as the default. We also make the property read-only because we don’t want to have the number of legs changed after the Animal object is instantiated. However, by making the property Overridable, we allow designers of a derived class (perhaps a Monkey class) to Override the property and specify a different number of legs.
Public Class Animal
Protected _NumberOfLegs As Integer = 4
Public Overridable ReadOnly Property NumberofLegs() As Integer
Get
Return Me._NumberOfLegs
End Get
End Property
End Class
The following Monkey class inherits from the Animal class and provides it’s own implementation of the NumberOfLegs property. Note that in this derived class I am able to access the _NumberOfLegs variable directly in the base class and set it’s value because it is a protected member; therefore, I can do that within the constructor of my derived Monkey class even though the public property is a read-only property.
Public Class Monkey : Inherits Animal
Public Sub New()
Me._NumberOfLegs = 2
End Sub
Public Overrides ReadOnly Property NumberOfLegs() As Integer
Get
Return Me._NumberOfLegs
End Get
End Property
End Class
Another way to declare an overridable method is to declare it in the base class with the MustOverride keyword, instead of the Overridable keyword. Then the method is known as a “pure virtual function” in object oriented speak, and it means the designer of a derived class must redefine the method because the base class will have only the signature of the method and no implementation details.
Also, if any method in a base class is declared with the MustOverride keyword, then the class must also be defined with the MustInherit keyword, making the class an “abstract class.” An abstract class cannot be used to instantiate objects and can only be used as a base class.
This makes sense because if the base class does not define the implementation of a method, then we would not want an object of that class, since calling that method would produce no result.
In the earlier example where we used the Overridable keyword to declare the property and did not use the MustInherit keyword, it was possible to have both Animal objects and Monkey objects in our program.
Now, in this second scenario, it is not possible to have an Animal object in our program (an Animal object is an instance of the Animal class). We can have only Monkey objects because we declare the Animal class with the MustInherit keyword and provide no implementation details for the NumberOfLegs property.
Public MustInherit Class Animal
Protected _NumberOfLegs As Integer = 4
Public MustOverride ReadOnly Property NumberOfLegs() As Integer
End Class
Public Class Monkey : Inherits Animal
Public Sub New()
Me._NumberOfLegs = 2
End Sub
Public Overrides ReadOnly Property NumberOfLegs() As Integer
Get
Return Me._NumberOfLegs
End Get
End Property
End Class
Polymorphism
The concept of overridable methods is a powerful one and without it we could not have inheritance based polymorphism, one of the foundations of object oriented programming languages, because virtual functions (overridable methods) is the mechanism that implements polymorphic behavior in an object oriented language like VB.NET.
Polymorphism itself can be a difficult concept to understand but I’ll do my best to explain it here, and later I’ll show you some examples. For now, just remember that without polymorphism we could not say VB.NET is an object-oriented language.
The word “Polymorphism” literally means many forms and it’s indicative of the many forms a base class can spawn in its derived classes as each derived class can extend the functionality of the base class.
Note: In this context, when we say forms we don’t mean the windows that you can see on the screen when working in a visual programming environment like Visual Studio. Instead, here we are referring to the standard definition of the word as found in the dictionary: The shape and structure of something; the essence of something; a model for making a mold, etc.
The benefit of polymorphism is that at design time you do not need to know which overridable method in an inheritance chain will be called at run time. All you need to know is that if the method is called on a reference to a base class object, then the runtime can determine which method should be called based on the true type of the object assigned to the variable. This is what is meant by dynamic binding of a method and it’s implementation.
That may sound confusing. I know it did when I first heard it, so let’s see an example.
Here we have the same base class, but this time we have a MustOverride read-only property called RunningSpeed. This property tells us how fast a particular animal can run. Note that I declared the Animal class with the MustInherit keyword because I must to do this after I use the MustOverride keyword on any of it’s methods. Also, we now have two derived classes, a Monkey class and a Dog class. You’ll notice that each has a different RunningSpeed value.
Public MustInherit Class Animal
Protected _RunningSpeed As Integer = 20
Public MustOverride ReadOnly Property RunningSpeed() As Integer
End Class
Public Class Monkey : Inherits Animal
Public Sub New()
Me._RunningSpeed = 9
End Sub
Public Overrides ReadOnly Property RunningSpeed() As Integer
Get
Return Me._RunningSpeed
End Get
End Property
End Class
Public Class Dog : Inherits Animal
Public Sub New()
Me._RunningSpeed = 25
End Sub
Public Overrides ReadOnly Property RunningSpeed() As Integer
Get
Return Me._RunningSpeed
End Get
End Property
End Class
Now suppose we have a method called GetAnimalsRunningSpeed that looks like this:
Public Function GetAnimalsRunningSpeed( _
ByVal SomeAnimal As Animal) As Integer
Return SomeAnimal.RunningSpeed
End Function
There are two important observations to make here:
1. This function accepts a reference to an Animal object.
2. Since we declared the Animal class using the MustInherit keyword, we cannot create an instance of an Animal class.
So how do we call the GetAnimalsRunningSpeed if we cannot instantiate an Animal object? This is where polymorphism takes over.
You probably already know or heard that in VB.Net everything inherits from the Object class and therefore everything is an Object type. And you may also know that you can store anything in a variable that is declared as an Object. This holds true because the Object class is the ultimate base class for any other class created in VB.NET. So even if you create a class and don’t inherit from any other class, you are still inheriting from the Object class because VB.NET will do this implicitly behind the scenes without requiring you to type the words “Inherits Object” in your class declaration. This means that the following two class declarations are the same:
Public Class classA End Class Public Class classA : Inherits Object End Class
Why am I explaining all this?
In VB.NET, anywhere in a program that requires an instance of an Object variable, you can safely use an instance of any other class because, as I stated earlier, everything in VB.NET inherits from the object class and is an object, whether or not you explicitly inherit from the object class.
This rule extends to any class created in VB.NET.
In our example with the Animal class, anywhere that an Animal object is required, we can safely substitute an instance of a class that inherits from the Animal class. That means we can pass a Dog object or a Monkey object to the GetAnimalsRunningSpeed function because that function requires an Animal object, and the Dog object and Monkey object both inherit from the Animal class. The ability to use an object of a derived type anywhere an object of a base type is expected is what makes polymorphism possible.
The runtime doesn’t care that the true type of the variable that is passed to GetAnimalsRunningSpeed is not an Animal object as long as it is an instance of a class that inherits from the Animal class. When the function is executed, then the runtime will examine the true type of the variable and call the RunningSpeed property that is defined in the class of the true type of the variable. That means if you call GetAnimalsRunningSpeed using a Monkey object like this:
Dim m As New Monkey
MsgBox("The running speed of a monkey is " _
GetAnimalsRunningSpeed(m).ToString)
You will get a message box displaying the RunningSpeed value that is defined for the Monkey object.
If you call GetAnimalsRunningSpeed using a Dog object like this:
Dim d As New Dog
MsgBox("The running speed of a dog is " _
GetAnimalsRunningSpeed(d).ToString)
You will get a message box displaying the RunningSpeed value that is defined for the Dog object. This happens even though GetAnimalsRunningSpeed expects an Animal object.
How all this relates to real life programming.
Inheritance based polymorphism seems cool and all that, by why would you want to use it in real life programming projects?
The answer is simple: It saves you lots of programming time and effort, makes your code neater and easier to understand, places critical sections of code in one spot, and makes it easier to incorporate changes and fixes.
In our example the GetAnimalsRunningSpeed function never has to change. Today it deals only with Monkey and Dog objects, but if you create other classes that inherit from the Animal class (perhaps a Cat class, a Horse class, etc.) you will never have to change the GetAnimalsRunningSpeed function to recognize those new classes. They inherit from the Animal class and therefore must have any public method declared in the Animal class. And that means an object instantiated from each of those classes can be seamlessly passed to the GetAnimalsRunningSpeed function.
Before object oriented languages became popular in software development, most programmers used languages that did not support polymorphism (most programmers did not even know what that meant!). A function such as GetAnimalsRunningSpeed would have to test for the kind of animal it was working with and would have to call the correct method based on that conditional statement. If a new animal were to be incorporated into this program, the GetAnimalsRunningSpeed function would have to be modified to test for that new animal so that it would know how to handle the call. This could get messy as more and more animals are added to the program (the animal kingdom is very large) and it makes it easy to introduce bugs into your program! Instead, using Inheritance and Polymorphism, each new derived class can contain all of the information necessary to perform the work for that specific type. This eliminates the need to make modifications to the base code and simplifies your coding efforts.
The examples in this article are trivial and designed for demonstration purposes only. In a real application the complexity level rises dramatically, and that is when you will realize the true power of inheritance based polymorphism.
For example, imagine a scientific research application that deals with formulas and with experiments and is designed to manipulate the settings of machinery during those experiments. Imagine that each experiment has different requirements and settings based on the material that is used in the experiment.
In that situation it may be possible for hundreds of different materials to be processed by an application.
One possible scenario here is to have a base class called Material with the methods for describing the necessary machinery settings when dealing with the material. Then you could derive classes from the Material class for each specific type of Material. In the derived classes you could include the necessary data that applies to that specific material. This means the actual code that manipulates the machinery during the experiment would not have to change each time a new material is introduced to the application. The chance for introducing errors into the application because of constant modification to the base code is eliminated since each new derived class can specify the new information that pertains to the new material without affecting any previous code!
Summary
The Overrides keyword, in conjunction with the Overridable and MustOverride keywords, is how VB.NET implements inheritance based polymorphism. The Overridable and the MustOverride keywords are used in a base class to designate methods that can be overriden. The Overrides keyword is used in a derived class when overriding one of those methods.
If you do not get familiar with the use of these keywords you will not be able to make use of the VB.NET mechanism for implementing this powerful concept into your programs. As a result, your applications may not be able to handle complex design problems efficiently and you may find yourself involved in programming maintenance activities and in bug fixes more than would otherwise be necessary.
You could avoid that by learning about polymorphism in VB.NET, familiarizing yourself with these keywords, and moving on up to the next level of programming skill in your career.
In the space of one article I could not cover everything that has to do with inheritance, polymorphism, and the related keywords. In fact, I’ve only scratched the surface. If you would like to read more, here are several links to additional information:
Using Inheritance in the .NET World, Part 1
Using Inheritance in the .NET World, Part 2
In this installment we covered the Overrides keyword and other related keywords along with the concept of polymorphism. In the next installment we will tackle the Shadows keyword, discussing its purpose and how to use it. I’ll see you then!
No Comments yet.


