Encapsulation in VB6

This is a continuation of the previous article “OOP in VB6?”. If you haven’t read that one, be sure to read it first and then get back to this. You can read the previous article by clicking on the title “OOP in VB6?” below:

If you want to code-along with me, we’ll be using the formless VB6 application since we don’t necessarily need a form to illustrate this concept.

Creating the Class

Okay, so to do this we’ll need to a “class” module. You can do this from the project window, right-click on the Project, then click “Add” and then “Class Module”

Go on a proceed to select “Class Module” and click “Open”

You’d end up with a blank class module like below:

Next, let’s rename this from “Class1” to something more descriptive for our demo “CBankAccount”.

We use the capital “C” prefix just to indicate it’s a class module (“M” for basic module, “F” for form class)

Writing the Class

Okay, let’s type the initial codes for this class. We’ll just need a single data to hold the balance and the rest will be methods that will encapsulate this data.

Here are the codes, so you can just copy + paste them:

Option Explicit

Private mdblBalance                         As Double

Public Sub Deposit(ByVal Amount As Double)
    If Amount < 0 Then
        '
        ' prevent negative deposits
        '
        Err.Raise vbObjectError + 101, , "Negative deposits are not allowed"
    Else
        '
        ' you may require "minimum deposit" verification here
        ' but for this demo, we'll just accept any positive
        '
        mdblBalance = mdblBalance + Amount
    End If
End Sub

Next, we’ll create another function to encapsulate retrieving the balance:

Public Function GetBalance() As Double
    '
    ' we are just going to return the value of our
    ' protected (or encapsulated) variable
    '
    GetBalance = mdblBalance
End Function

The last method is for withdrawing from this account:

Sub Withdraw(ByVal Amount As Double)
    '
    ' you can do this at least 2 ways, either require Amount to be negative
    ' and then add it to balance, effectively substracting it.
    ' ---
    ' or ensure it's positive and perform substraction, which is what
    ' we'll do on this demo.
    '
    
    Amount = Abs(Amount)        ' ensure the value is positive using Abs(olute) function
    
    If Amount > GetBalance Then
        '
        ' prevent withdrawing more than what is there
        '
        Err.Raise vbObjectError + 201, , "Amount to be withdrawn is larger than current balance"
    End If
    
    mdblBalance = mdblBalance - Amount
End Sub

Testing the Class

The class is done, so now we’ll switch to and reuse the existing basic module (Module1) and write our test codes there.

First, remove the codes we wrote inside the “Sub Main” procedure, or remove all codes then copy + paste the code below:

:: Happy Path

Happy Path just means we’re using the class as it’s intended, making sure we pass the right values and everyone and everything is happy 🙂

Option Explicit

Sub main()
    happy_path
End Sub

Private Sub happy_path()
    ' not recommended to auto-instantiate, but for brevity we will
    Dim cba                                 As New CBankAccount
    
    Debug.Print "Initial Balance: " & cba.GetBalance
    
    cba.Deposit 100
    Debug.Print "After Deposit: " & cba.GetBalance
    
    cba.Withdraw 35
    Debug.Print "After Withdrawal: " & cba.GetBalance
End Sub

Now run this project and you should see that it works as expected (from the Immediate window):

:: Negative Testing

This is the opposite of Happy Path since our objective in this test is to intentionally break our code 🙂

I know it sounds weird, but this not only ensures you’ve tested it completely, but also ensures we handled all the exceptions properly.

But before we even do that, we have to make sure the IDE is configured to allow us to perform the tests correctly.

So go to the “Tools” menu then click on “Options…”:

Navigate to the “General” tab, and under “Error Trapping”, select the “Break on Unhandled Errors”.

This is critical if you want to catch the exceptions, like the ones we made inside the class via “Err.Raise” calls.

Now we can move on to writing our negative test case:

NOTE: we have commented out the “happy_path” line in Sub Main so it doesn’t get executed when we test it.
But you can leave it be.

Sub main()
    'happy_path
    negative_tests
End Sub


Private Sub negative_tests()
    ' not recommended to auto-instantiate, but for brevity we will
    Dim cba                                 As New CBankAccount
    
    ' VB6 does not have TRY..CATCH so we'll emulate that via On Error Resume
    ' BUT don't use this to hide errors; that's lazy and bad :)
    On Error Resume Next
    cba.Deposit -45
    If Err.Number <> 0 Then
        Debug.Print Err.Description
    End If
    
    cba.Withdraw 88
    If Err.Number <> 0 Then
        Debug.Print Err.Description
    End If
    
End Sub

We test it and verify that it indeed raised the errors we defined in our class:

I’ll will cover the next one (“Polymorphism”) on the next article so stay tuned 🙂

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

https://github.com/vegitz/codes/tree/master/0008%20Encapsulation%20in%20VB6

Leave a Comment