Inheritance Keywords

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.

Forcing or Preventing Inheritance

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.

Overriding Properties and Methods

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.

Figure 5.1. Overridable methods are shown in the Method Name drop-down when you inherit within VB .NET.


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

MyBase and MyClass

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.

Figure 5.2. MyBase allows derived methods to call the implementation in the base class, even if the derived class overrides that method.


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.

Figure 5.3. MyClass can call implementation code in the same class running the current routine, regardless of whether the client has overridden that method elsewhere.


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).

Understanding Accessibility and Inheritance

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

  • Friend— Accessible within the project but not outside 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.

Figure 5.4. The accessibility of various methods, based on the accessibility modifiers.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.116.50