Parameterized Constructors in VBA

If you are familiar with other object-oriented programming languages, you are likely familiar with the concept of constructors:

In class-based object-oriented programming, a constructor (abbreviation: ctor) is a special type of subroutine called to create an object. It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.

A constructor that accepts arguments is known as a parameterized constructor.  A constructor that does not require arguments is known as a default constructor.

The VBA language specification does not allow for parameterized constructors.

VBA does support default constructors, in the form of the Class_Initialize lifecycle handler:

"If a class defines a Class_Initialize lifecycle handler, that subroutine will be invoked as a method each time an instance of that class is created..."

Unfortunately, there is no way to pass parameters to the Class_Initialize handler.  Thus, it is impossible in VBA to require calling code to provide arguments when creating a class.  This differs from almost every other object-oriented programming language, as most OOP languages support parameterized constructors.

Factories to the Rescue

"In object-oriented programming (OOP), a factory is an object for creating other objects..." (Wikipedia)

To work around this shortcoming in VBA, I create a standard module that holds all the parameterized constructors for each of my applications.  I name this module, "xxFactory," where the "xx" is an application-specific prefix that distinguishes the module from other modules that I import from my standard code library.  For example, in my TaxColl2k application, I have a StringFunctions module that I keep in sync with my code library and a tcFactory module whose code has no value outside of the TaxColl2k application.

Example factory function

Here is an example of one of my factory functions:

Function NewSchoolObject(SchoolDist As String, _
                         DistrictID As String) As oSchool
    Set NewSchoolObject = New oSchool
    NewSchoolObject.Init SchoolDist, DistrictID
End Function

Naming conventions

There are some naming conventions I want to point out in the above code.  Since there is nothing in VBA itself that requires the use of these functions, a strong and consistent naming convention greatly improves code quality.

The underlying object is named oSchool.  I use a variety of prefixes when naming my class modules.  The "o" prefix is reserved for classes that represent real-world objects.  These kinds of objects in my applications frequently have a one-to-one relationship with database tables, too.

The name of the factory function comprises three parts:

  • "New": a literal string that prefixes every one of my factory function names
  • "School": the underlying object name stripped of its prefix
  • "Object": a literal string that I append to each factory function name

Thus, every factory function name follows this format: New{class name}Object.

Finally, the underlying class has a public method named Init that takes the same parameters as the factory function.  The Init method must be public, but it should only ever be called from a factory function.

Usage

Here's how the code looks without using the factory function:

Dim School As oSchool
Set School = New oSchool
School.SchoolDist = "X"
School.DistrictID = 42

Here's the same code with the factory function:

Dim School As oSchool
Set School = NewSchoolObject("X", 42)

Image by LEEROY Agency from Pixabay