There are a number of keywords associated with inheritance. Remember that by default, all classes you create are inheritable. You inherit from classes using the Inherits keyword. The class from which you inherit is then known as the base class. The Inherits keyword can be used only in classes and interfaces. It is important to point out that a derived class can only inherit from one base class.
The NotInheritable modifier is used to mark a class as not inheritable; in other words, it cannot be used as a base class. If you were to modify the Person class in your InheritanceTest project, it would look like this:
Public NotInheritable Class Person
If you change the Person definition to look like the preceding line, Student will no longer be able to inherit from Person.
In contrast to the NotInheritable modifier, there is also a MustInherit modifier. MustInherit says that a class cannot be instantiated directly. Instead, it must be inherited by a derived class, and the derived class can be instantiated.
If you changed Person to include the MustInherit keyword, it would look like this:
Public MustInherit Class Person
Now, you would not be able to use the following line of code in the client:
Dim myPerson As New Person
However, you would still be able to inherit Person in your Student class, and your client could instantiate Student.
When you inherit a base class, the properties and methods cannot be overridden, by default. Given your earlier example in InheritanceTest, you could not have created a function named Enroll in Student because one existed in Person.
There is a modifier, NotOverridable, that says a particular property or method cannot be overridden. Although methods are normally not overridable, you can use this keyword only in a unique case: If you have a method that is already overriding a base method, you can mark the new, derived method as NotOverridable.
If you want to allow a property or method to be overridden, you can mark it with the Overridable modifier, as shown here:
Public Overridable Function Enroll() As Boolean
Now, your Student can create its own Enroll method. To do so, your client will have to use the Overrides modifier, so it would look like this:
Public Overrides Function Enroll() As Boolean
What happens if the Enroll function is marked as Overridable in the base class, but you don't override it in the derived class? In this case, it acts like any other method in the base class, and calling from the derived class will actually call the implementation of the function in the base class.
In the VB .NET IDE, it is also possible to use the drop-down lists at the top of the code window to override methods or implement interfaces. As you can see in Figure 5.1, there are two classes in the file. Class Student is inheriting class Person, and in so doing, is able to override the Enroll method. If you change the Class Name drop-down to (Overrides), Enroll shows up in the Method Name drop-down, and can be used to create the stub of the derived Enroll method in Student.
There is also a MustOverride modifier. This forces a derived class to override the property or method. The MustOverride modifier changes the structure of the property or method. Because the property or method must be overridden, you do not put any implementation code in it. In fact, there is not even an End Property or End Sub or End Function when using the MustOverride modifier. If a class has even a single property or method with the MustOverride modifier, that class must be marked as MustInherit because the method can be used only if it is overridden in another class. Therefore, the class must be inherited to be used.
For example, here you have a base Transportation class that has a method, Move, that is marked as MustOverride. This means that Transportation must be marked as MustInherit. The Train class inherits from Transportation, and then overrides the Move method.
Public MustInherit Class Transportation MustOverride Function Move() As Boolean End Class Public Class Train Inherits Transportation Public Overrides Function Move() As Boolean 'code goes here End Function End Class
Although you can override a base class property or method in your derived class, you can still access the properties or methods in the base class using the MyBase keyword. This allows you to call base class members even though you have overridden them in your derived class.
For example, assume that you wanted to have a Transportation class, with an overridable function called Move. Train then inherits from Transportation, and implements its own Move method, overriding the one in Transportation. Now, from within Train, you can call the Move method in Train or the one in Transportation.
The method CallMethods calls first the Move in Train, and then the Move in Transportation. The user will see two message boxes. The first will have the text Hello from the Train class, whereas the second will have the text Hello from the Transportation class.
Figure 5.2 shows a diagram of how the code works. The Move in CallMethods uses the Move in the Train class, but MyBase.Call executes the code in the base class, Transportation.
Public Class Transportation Overridable Function Move() As Boolean MsgBox("Hello from the Transportation class") End Function End Class Public Class Train Inherits Transportation Public Overrides Function Move() As Boolean MsgBox("Hello from the Train class") End Function Public Sub CallMethods() Move() MyBase.Move() End Sub End Class
Related to MyBase is MyClass. Assume that, in your base class, you have method A calling an overridable method B. If you want to verify that the method B you call is the one you wrote in the base class, and not the derived, overridden method B in the derived class, call method B with the MyClass qualifier, as in MyClass.B.
For example, assume that you have a Transportation class that has two methods: MakeReservation and BuyTicket. MakeReservation calls BuyTicket. MakeReservation and BuyTicket are both overridable. Your Train class can inherit Transportation, and create a BuyTicket method that overrides the BuyTicket in Transportation. If you don't create a MakeReservation in Train, your call to MakeReservation will use the code in the Transportation class. However, if the code in Transportation.MakeReservation calls BuyTicket, by default you'll call the BuyTicket you've created in Train. Here is the code:
Public Class Transportation Overridable Function MakeReservation() As Boolean 'CheckSchedule BuyTicket() 'etc End Function Overridable Function BuyTicket() As Boolean MsgBox("Generic Transportation implementation") End Function End Class Public Class Train Inherits Transportation Public Overrides Function BuyTicket() As Boolean MsgBox("Train-specific implementation") End Function End Class
Now, suppose that you want the MakeReservation to call the BuyTicket method in Transportation, even if Train overrides BuyTicket. To accomplish this, just change Transportation.MakeReservation to this:
Public Class Transportation Overridable Function MakeReservation() As Boolean 'CheckSchedule MyClass.BuyTicket() 'etc End Function
Figure 5.3 shows this in action. First, a client instantiates Train, which is derived from Transportation. The client then calls Train.MakeReservation. Because Train does not override MakeReservation, the MakeReservation in Transportation is called. The first line in MakeReservation calls BuyTicket. However, because Train does override BuyTicket, that method is used. The next line in Transportation calls MyClass.BuyTicket, which calls the BuyTicket method in the same class in which MakeReservation is running.
It's important to note that if your Train class overrides MakeReservation, MyClass will not come into play. The reason is that the implementation of the base MakeReservation is gone, so the MyClass.BuyTicket is overridden and will not be called (unless Train calls MyBase.BuyTicket for some reason).
Accessibility can be a bit complicated when using inheritance. There are several modifiers used to set the accessibility. They are:
Public— Accessible throughout the project and any project that references it
Protected— Accessible within the class in which it was created, or any class that is derived from the base class containing the protected element
Protected Friend— Accessible within the same project, in a derived class, or both
Private— Not accessible outside the module or class containing the element
To see this in an example, take the following code. You have three classes in the class library: Person, Student, and Foo. Person is a base class, containing one Sub of each accessibility type mentioned above. Student is a derived class of Person. Foo is a class in the same project, but it does not derive from Person.
Next, you have a client application that instantiates the Student class only. Notice what Subs from Person make it to Student, to Foo, and to the client. The code for the class library follows:
Public Class Person Public Overridable Sub PublicSub() End Sub Friend Overridable Sub FriendSub() End Sub Protected Overridable Sub ProtectedSub() End Sub Protected Friend Overridable Sub ProtectedFriendSub() End Sub Private Sub PrivateSub() End Sub End Class Public Class Student Inherits Person Public Overrides Sub PublicSub() End Sub Friend Overrides Sub FriendSub() End Sub Protected Overrides Sub ProtectedSub() End Sub Protected Friend Overrides Sub ProtectedFriendSub() End Sub End Class Public Class Foo Dim myStudent As New Student() Public Sub Test() myStudent.PublicSub() myStudent.FriendSub() myStudent.ProtectedFriendSub() End Sub End Class
Notice that Student, which is derived from Person, can see everything but Person's PrivateSub method because it is marked as private and is therefore only visible to Person.
Foo, on the other hand, can only see the PublicSub, FriendSub, and ProtectedFriendSub. ProtectedSub can be seen only by the class in which it exists and any class derived from that base class.
Finally, take the following client code that instantiates a Student object:
Imports AccessibilityTest Public Class Form1 Inherits System.Windows.Forms.Form Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim myStudent As Student myStudent.PublicSub() End Sub End Class
Notice that in the client, the only method that is accessible is the PublicSub method. Figure 5.4 shows each Sub and how far it is visible in each case.
3.138.116.50