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