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