Polymorphism in VB6

Continued from the last article I posted, we’re now going to cover PolyMorphism in VB6.

To do that, we need an abstract class (interface), and at least one concrete class (implementation), so let’s go ahead and do that.

Creating the abstract class (Interface)

Using the same project from last article, we’re going to add a new class.

But this class will be different, it will serve as an “interface” class — or a class that has no implementing code. So go ahead and add a new class to the project.

Rename this new class from Class1 to iBankNetwork.

Note that we used an “i” prefix, so we would know that it’s an Interface class just by looking at its name.

Now type the following on to that class:


Public Function Validate(ByVal account_number As String) As Boolean
    '
    ' place no implementation here, this is just an interface.
    ' the actual code will be on the concrete class(es)
    '
End Function

NOTE:

Do not use underscore in the function name. It will not work due to how VB6 does things with names, which you’ll see later.

Bancnet Implementation

We are now ready to implement the Bank Network interface.

Create another class and rename it “CBanknet”

In this class, we’ll implement the code we defined in the interface class, and we do that by using the “Implements” keyword.
So enter the following line to this class:

Implements iBankNetwork

Once you’ve typed that, seems like nothing happened but go ahead and click the “General” dropdown menu and you will see a new entry called “iBankNetwork”.

Click that.

The IDE will generate an empty function definition, similar to the one we defined in the iBankNetwork class but with slight difference —- the function name is a combination of the class name and the function name.

Notice the underscore that was used by VB6 to “separate” the class (interface) name and the function name?

That’s why we don’t use underscores when defining methods or properties in an interface class. Later, I’ll show you what happens if you do accidentally or intentionally added an underscore, but for now let’s continue with the program.

Under/inside this blank function template, type the following:

Private Function iBankNetwork_Validate(ByVal account_number As String) As Boolean
    On Error GoTo ErrorHandler
    
    ' do a simple validation for demo purposes
    If Len(account_number) < 10 Then
        Err.Raise vbObjectError + 101, , "Account number is invalid"
    End If
    
    ' if all goes well, we validate the account
    iBankNetwork_Validate = True
    
    Exit Function
    
ErrorHandler:
    ' display the error
    Debug.Print Err.Description
    iBankNetwork_Validate = False
    
End Function

MegaLink Implementation

Now let’s create another implementation so we can really test how PolyMorphism works.

Similar to how we did BancNet class, add another class to the project and rename it to “CMegaLink” and type the following code:

Implements iBankNetwork


Private Function iBankNetwork_Validate(ByVal account_number As String) As Boolean
    On Error GoTo ErrorHandler
    
    ' do a simple validation for demo purposes
    If Left(account_number, 1) <> "5" Then
        Err.Raise vbObjectError + 101, , "Account number is not recognized"
    End If
    
    ' if all goes well, we validate the account
    iBankNetwork_Validate = True
    
    Exit Function
    
ErrorHandler:
    ' display the error
    Debug.Print Err.Description
    iBankNetwork_Validate = False
End Function

Ready for Testing

Okay, time to combine all these ingredients so we can finally see them in action!

Go back to the “Module1” basic module that we have in the project and create a new sub routine called “test_validation” with the following codes:

Private Sub test_validation()
    Dim account_number                      As String
    Dim network                             As iBankNetwork
    
    account_number = "123456789"
    
    ' test using bancnet (should fail since it is less than 10-digits long)
    Set network = New CBancnet
    network.Validate account_number
    
    ' test using megalink (should fail since it does not start with zero)
    Set network = New CMegaLink
    network.Validate account_number
    
End Sub

Next, we have to call this sub routine from the “main” sub routine so we can see it work.

Comment out the previous two lines we had and add a call to our new sub routine like this:

Sub main()
    'happy_path
    'negative_tests
    test_validation
End Sub

Run the code and you should see the results in the “Immediate” window pane (like below):

What kind of magic is that?

So how did that happen?

We created a variable of type iBankNetwork. This is the class we created that has no implementing code.

The magic in in the “Implements” keyword, which basically tells VB6 that the classes implementing the iBankNetwork is “compatible” with the abstract class, that’s why we can assign the Bancnet and MegaLink instances to it.

Notice how we were able to create an instance of iBankNetwork with “new CBancNet” and “new CMegaLink”?

Once we called the method “Validate”, VB6 routed the call to the corresponding class instance and executed the implementing code.

Where to go from here?

This pattern or design allows you to create extendable/extensible systems with very few to zero modifications on the core logic. You could implement the OCP (Open-Closed Principle) using PolyMorphism and you’ve seen above.

Other ideas that could use this technique:

  • Search Engine (implementation for Google, DuckDuckGo, FireFox, etc.)
  • Database Backend Layer (implementation for Oracle, MSSQL, MySQL, PostGres, etc.)
  • Password Validation (implementation of “at least one number”, “must have upper case”, etc)
  • Data Retrieval (implementation for direct-DB, web service calls, etc.)

These are just some of the things that can use PolyMorphism and there’s so much more use cases out there.

Caveat(s)

Of course, nothing is stopping you or a user of your iBankNetwork from instantiating it. You can easily do this instead:

set network = new iBankNetwork

And that would be valid. But the idea of abstract classes is that they shouldn’t be creatable, right?

Well, it is possible… you just have to create the class outside of the project. I’ll cover that one in future articles in case some of you are curious as to how to do it.

What if I don’t use it?

If you don’t like the added work to set this system up, you can always do it the traditional way. Again, nothing is stopping you from doing it, but when you start working on large system and with a large team, you’ll soon realize how incredibly hard it is to maintain and extend it.

Without using PolyMorphism, your code will look like this:

if network = "bancnet" then
   dim network as CBankNet
   set network = new CBancNet
   ...
elseif network = "megalink" then
   dim network as CMegaLink
   set network = new CMegaLink
   ...
end if

That’s fine, but what if you need to support another network in the future?

You’d be opening this code up again and adding a new “elseif” condition, right? Plus you’d probably be doing multiple variable names like netbancnet and netmegalink and do a specific instantiation.

One more thing…

I didn’t forget what I promised, so here’s what’s going to happen if you put underscore in the function name (note that I created a new dummy project to illustrate this so we don’t have to do this on the project we just made):

As you can see from the screenshot, VB6 is complaining that the “dowe” class needs to implement the “wont_work_function” even if it already does that.

This is a VB6 problem, and we just have to remember not to use underscores when defining methods in abstract classes and we’ll be fine. 🙂

Thank you and let’s keep reading and learning!

Here’s the link to my GitHub page for the full source codes:

https://github.com/vegitz/codes/tree/master/0009%20Polymorphism%20in%20VB6

Leave a Comment