Polymorphism

Polymorphism is often considered to be directly tied to inheritance (which we'll discuss next). In reality, however, it's independent to a large degree. Polymorphism means that we can have two classes with different implementations or code, but with the same interface. We can then write a program that operates upon that interface and doesn't care about which type of object it operates at runtime.

Polymorphism through Late Binding

For example, if we have a class called Square and another one called Cowboy then they may both have a method called Draw. We can write a program that tells an object to draw by calling the Draw method. This program won't care if it is working with a Square or a Cowboy - even though each object must obviously implement the Draw method differently.

If the Square class contains the following code:

Option Explicit

Public Sub Draw(Target As Form)
  Target.Line Step(0, 0)-Step(0, 100)
  Target.Line Step(0, 0)-Step(100, 0)
  Target.Line Step(0, 0)-Step(0, -100)
  Target.Line Step(0, 0)-Step(-100, 0)
End Sub

And the Cowboy class contains this code:

Option Explicit

Public Sub Draw(Target As Form)
  Target.Print "Draw from holster"
  Target.Print "Aim"
  Target.Print "Fire"
End Sub

Then we can put this routine in a form:

Public Sub DoDraw(SomeObject As Object)
  SomeObject.Draw Me
End Sub

This routine doesn't care if it is passed a Square or a Cowboy, even though the two classes are implemented in an entirely different fashion. Notice that the routine accepts a parameter of type Object. By doing this, we have allowed the routine to accept literally any object we care to send it. This simple example of polymorphism works in Visual Basic 4.0 as well as Visual Basic 5.0.

Visual Basic 4.0 implements polymorphism in the same manner as Smalltalk, by using something called late binding. We've just seen an example of late binding with the Draw method of the Square and Cowboy objects.

Late binding means that the Visual Basic compiler makes no effort to determine if calls to our objects are valid. All the checking takes place while the program is running. Each call to an object is checked as it's called, and an error is raised if the call turns out to be invalid.

Polymorphism with Early Binding

Visual Basic 5.0 retains this ability, but also implements a stricter form of polymorphism (similar to that found in C++) through its support of interface inheritance using the Implements keyword.

For example, if we create a Shape class with the following code:

Option Explicit

Public Sub Draw(Target As Form)

End Sub

Then we can use Shape as a base to create a Square class:

Option Explicit

Implements Shape

Public Sub Shape_Draw(Target As Form)
  Target.Line Step(0, 0)-Step(0, 100)
  Target.Line Step(0, 0)-Step(100, 0)
  Target.Line Step(0, 0)-Step(0, -100)
  Target.Line Step(0, 0)-Step(-100, 0)
End Sub

And we can also create a Circle class, again using the Shape class as a base class:

Option Explicit

Implements Shape

Public Sub Shape_Draw(Target As Form)
  Target.Circle Step(0, 0), 200
End Sub

With these classes defined, we can try them out. The following code accepts a parameter and then calls its Draw method:

Public Sub DrawShape(objSomeShape As Shape)
  SomeShape.Draw Me
End Sub

Notice the difference between this example and the previous one with the Square and Cowboy classes. Instead of accepting an Object type as a parameter, we're now able to accept a parameter of type Shape. We've ensured that the only objects passed to our routine will be shapes. Since we'd probably never use the Shape class as a base to build a Cowboy class, we don't have to worry about getting a Cowboy when we wanted a Square or Circle.

This uses early binding. Early binding occurs as the program is being compiled, which means that the compiler can help us out by doing type checking and by verifying that the properties and methods we call on the object are valid.