More About Inheritance
Unlike some other object-oriented languages, Visual Basic .NET only provides for single inheritance—a class can inherit only from a single parent class. Of course, that parent class can inherit from another class and so on. As I mentioned in Chapter 2, languages such as C++ permit you to inherit from multiple classes simultaneously. Problems from multiple inheritance are one of the largest sources of bugs in C++.
To fully understand objects, let's create another small class, Division, that inherits the functionality of our Employee class. As you can see by now, inherited classes are like an upside-down pyramid. A parent class is general—wide like the overturned base of a pyramid. As child classes inherit from parent classes, they become more and more specialized, or narrow. An inherited class enjoys the functionality of the parent class plus any specialized functionality it might implement.
Our Division class will be a bit more specialized and permit us to assign an employee to a division and indicate how long the employee has been in that division. Follow these steps to create the Division class:
Click Project | Add Class. Add another class module to the project as you did for the Employee class. Name the class Division.vb, and then click Open to add the empty class declaration to the project.
Replace the existing Division.vb class code with the following code.
Imports System Imports Employee.employees.Employee Imports Microsoft.VisualBasic.ControlChars Imports System.Windows.Forms Namespace CompanyDivision Public Class Division Inherits employees.Employee Private m_sDivision As String = "" Private m_iMonthsInDivision As Integer = 0 Sub New() MyBase.New() End Sub Sub New(ByVal fName As String, ByVal lName As String) MyBase.New((fName), (lName)) End Sub Overrides Function Serialize() As Boolean If ((m_sDivision <> "") And _ (m_iMonthsInDivision <> 0)) Then If MyBase.Serialize = True Then Return True Else Return False End If Else Return False End If End Function #Region "Division Properties" Property Division() As String Get Division = m_sDivision End Get Set m_sDivision = Value End Set End Property Property MonthsInDivision() As Integer Get MonthsInDivision = m_iMonthsInDivision End Get Set m_iMonthsInDivision = Value End Set End Property #End Region End Class End Namespace
Our project already includes the System reference, but we now have to add the System.Windows.Forms.dll reference. Click View | Solution Explorer to display the Solution Explorer, if necessary. Right-click References, and select Add Reference. You'll see the Add Reference dialog box again, shown in Figure 3-9. Select the assembly mentioned earlier, and then click OK.
Figure 3-9
Add a reference to System.Windows.Forms.dll.
The Solution Explorer should now look like Figure 3-10. You can see that the three references are included, along with the new Division.vb class module.
Figure 3-10
The Solution Explorer should look like this.
Most of what you learned about the Employee class applies to the Division class, so I won't review those concepts. We sandwiched the Division class within the CompanyDivision namespace. The Division class inherits all the functionality of the employees.Employee class.
Namespace CompanyDivision Public Class Division Inherits employees.Employee
The Division class's constructors are overloaded to provide multiple implementations of New. Remember that the first line in a constructor must be a call to the constructor of its parent class, in this case Employee. We call the Employee constructor with the MyBase keyword to ensure that the Employee class is fully initialized before we try to use any of its members within the Division class. Both overloaded constructors provide signatures for MyBase that match the constructors in the parent class.
Sub New() MyBase.New() End Sub
Notice in the following code the double parentheses around the parameters of the call to MyBase.New in the constructor that takes two strings as its arguments. It so happens that we are passing in both parameters by value. However, I've used this syntax to show how you can force an argument to be passed by value no matter how it is declared. While the parentheses are not needed here, this syntax is how you would force parameters to be passed by value even if the parent expected parameters passed by reference.
Sub New(ByVal fName As String, ByVal lName As String) MyBase.New((fName), (lName)) End Sub
The Serialize function in Division overrides the implementation in the parent Employee class. However, as I indicated earlier, we don't want to save an instance of a Division class if important fields have been accidentally omitted. The overridden Serialize method checks the Division class's private data fields. If those fields have been populated, the first and last name member fields in the parent Employee class need to be checked. We can check these fields by calling the parent class's Serialize method. This overridden method first checks to see whether the Division class's private variables have been set. If they have, MyBase.Serialize is called to ensure the names have been entered in the Employee class. If and only if both checks return True, the overridden method returns True to the caller.
Overrides Function Serialize() As Boolean If ((m_sDivision <> "") And _ (m_iMonthsInDivision <> 0)) Then If MyBase.Serialize = True Then Return True Else Return False End If Else Return False End If End Function
Virtual Methods
All Visual Basic .NET methods are virtual methods, which means that if both the parent class and the child class include methods with the same name, the child class's implementation of the method is always called first when the method is invoked from the outside world. The method that is called is always the one that's included in the class used to create the object. If we create a type Employee class, its Serialize method is invoked. If we create a child class, Division, that inherits from the parent Employee class, it's the Serialize method implemented in the Division class that's called.
On the other hand, we might inherit a class and implement a method only in the parent class. When the method is invoked, Visual Basic .NET does not find it in the child class, so it searches up the inheritance chain until it finds the method in the parent class. But, because all methods are virtual, searching always starts in the child class at the bottom of the hierarchy and moves upward.
In the same way that you can prevent a method from being overridden by using the NotOverridable keyword, if you don't want another class to inherit our entire Division class, adding the keyword NotInheritable ensures inheritance will not happen.
Public NotInheritable Class Division Inherits employees.Employee