Inheritance in VB.NET
Inheritance is the idea that one class, called a subclass, can be based on another class, called a base class. Inheritance provides a mechanism for creating hierarchies of objects. For example, a dog is a mammal and a collie is a dog. Thus the dog class inherits the properties and methods of the mammal class, and the collie class inherits from both dog and mammal.
The objects in a hierarchy have two different types of relationships to one another, referred to in object-oriented parlance as HasA and IsA relationships. For example, a Collie IsA dog and HasA tail. Implementation inheritance is the object-oriented feature that supports IsA relationships. Containment supports HasA relationships. Implementation inheritance is also another way that VB.NET supports polymorphism. A function might accept a parameter typed as mammal and then an object that is derived from mammal can be passed in as the parameter.
Implementation Inheritance
Since version 5, Visual Basic has supported interface inheritance through the implements keyword. In previous versions of VB, the idea of using an existing class as the starting point in the development of a new class wasn't possible. This language feature is known as implementation inheritance. Now in VB.NET, implementation inheritance has been added to the language.
Previous versions of Visual Basic were targeted to COM development, which discouraged the use of implementation inheritance. Visual Basic.NET, on the other hand, is targeted for the .Net Framework, which is based on implementation inheritance.
Support for implementation inheritance is perhaps the biggest change in Visual Basic.NET. Table 3.1 shows the new keywords that have been added along with new statements and methods.
Table 3.1 New Language Elements for Implementation Inheritance
Element |
Context |
Description |
Inherits |
Class Statement |
Indicates the class from which the new class inherits |
NotInheritable |
Class Statement |
Indicates that a class that cannot be inherited from |
MustInherit |
Class Statement |
Indicates a class that must be inherited by another class |
Overridable |
Procedure |
Indicates a procedure that can be overridden by a subclass |
NotOverridable |
Procedure |
Indicates a procedure that cannot be overridden in a subclass |
MustOverride |
Procedure |
Indicates a procedure that must be overridden in a subclass |
Overrides |
Procedure |
Indicates that a procedure is overriding a procedure in a base class |
MyBase |
Code |
Allows code in a class to invoke code in the base class |
MyClass |
Code |
Allows code in a class to invoke code in itself |
Protected |
Function, Sub, Field, Property |
Indicates that code in a child class can access this |
The example in Listing 3.9 shows a number of the new keywords in action. The code describes a class with four properties and one method. Any class that inherits from this class must override the ClassName property. No class that inherits from this class can override the BaseClassName property. Any class that inherits from this class can freely override the remaining properties and methods.
Listing 3.9 Person Class
Public Class Person Protected c_sFirstName as String Protected c_sLastName as String MustOverride ReadOnly Property ClassName() as String Get ClassName = "Person" End Get End Property NotOverridable ReadOnly Property BaseClassName() as String Get BaseClassName = "Person" End Get End Property Overidable Public Property FirstName() as String Get FirstName = c_sFirstName End Get Set(ByVal Value as string) c_sFirstName = Value End Set End Property Overidable Public Property LastName() as String Get LastName = c_sLastName End Get Set(ByVal Value as string) c_sLastName = Value End Set End Property Overridable Sub Speak() Console.WriteLine("I am " & c_sFirstName & " " & c_sLastName) Console.WriteLine(" and I am a Person.") End Sub End Class
This example illustrates VB.NET's implementation of inheritance. In keeping with the language's design goals, VB requires that everything be very explicit. Table 3.2 compares some of the VB.NET keywords used to control the accessibility of classes and class members with their C# equivalents. In my opinion, the VB.NET keywords are much clearer than the C# keywords.
Table 3.2 VB Keywords Compared to C# Keywords
VB.NET |
C# |
NotInheritable |
Sealed |
MustInherit |
Abstract |
MustOverride |
Virtual |
Inherits |
: |
Listing 3.10 illustrates a class that inherits from the Person class.
Listing 3.10 NewPerson Class
Public Class NewPerson Inherits Person MustOverride Overrides Public ReadOnly Property ClassName() as String Get ClassName = "NewPerson" End Get End Property Overrides Sub Speak() Console.WriteLine("My name is " & c_sFirstName & " " & c_sLastName) Console.WriteLine(" and I am a new person.") End Sub End Public
This class shows a number of new keywords in use. Inherits indicates the class inherited. The ClassName property accessibility is set to MustOverride and Public, indicating that any class that inherits from this class must override this property. The Overrides keyword indicates that the ClassName property and the Speak method from the base class are being overridden by the new class.
c_sFirstName and c_sLastName aren't defined in the new class. They were defined in the base class, and their accessibility was set to protected. We will examine the accessibility modifiers in more detail in Chapter 4, "Methods, Properties, and Events."
Effective Implementation Inheritance
Analysis and design are paramount to an effective solution using implementation inheritance. VB.NET encourages developers to take time out to design because it requires developers to be very explicit about their intentions.
Class methods and properties must be marked as Overridable to allow inheritance. A class that inherits from a base class must mark methods that are being overridden with the Overrides keyword. Finally, if a class cannot be inherited from, this must be indicated with the NotInheritable keyword.
The requirement that a developer explicitly define his intentions helps to alleviate a problem known as "the fragile base class."
An example of the fragile base class problem is when a base class adds a new method that has the same name as a method name in a class that inherits from the base. The developer of the subclass never intended the method in the subclass to override the base class, but now this is exactly what has happened. This can cause problems with how clients use the class.
This problem cannot occur in VB.NET because of the declarative syntax required.
Containment
Containment, as we saw earlier, is the mechanism for implementing HasA relationships. Containment is actually rather simple, and isn't supported by anything specific within a language. In VB, for one object to have a HasA relationship to another, the first object will simply hold an instance of a object. For example, in my Person class, if I wanted to define a HasA relationship to the person's dog, I would simply add the code shown in Listing 3.11.
Listing 3.11 Containment Illustrates HasA Relationships
Private c_oDog as Dog Public Property MyDog() as Dog Get MyDog = c_oDog End Get End Property Public Sub GetADog(ByVal Breed as String, ByVal Name as String) c_oDog = New Dog(Breed,Name) End Sub