Class (Static) Methods in VBA
I wonder, whether it is possible to create class-methods in VBA. By class-method I mean methods that can be called without having an object of the class. The 'static'-keyword does that trick in C++ and Java.
In the example below, I try to create a static factory method.
Example:
'Classmodule Person'
Option Explicit
Private m_name As String
Public Property Let name(name As String)
m_name = name
End Property
Public Function sayHello() As String
Debug.Print "Hi, I am " & m_name & "!"
End Function
'---How to make the following method static?---'
Public Function Create(name As String) As Person
Dim p As New Person
p.m_name = name
Set Create = p
End Function
'Using Person'
Dim p As New Person
p.name = "Bob"
p.sayHello 'Works as expected'
Set p2 = Person.Create("Bob") 'Yields an error'
1. Create a normal class containing the public method(s) you need to be 'static'
2. Include a public method [in this 'static' class] that initialises the [private] 'static fields' within the class (it can take parameters if you wish)
3. Create a module acts as a factory
Public Function CreateStaticClass(parameters for 'constructor') As StaticClass
Dim static As StaticClass
Set static = New StaticClass
Call StaticClass.Constructor(pass in parameters)
Set CreateStaticClass = static
End Function
4. you can now use the 'static' class by calling CreateStaticClass('parameters').MethodName('parameters') there is no need to initialise the instance as that is done by the factory method
5. (Optional) If you want to enforce singleton instances you can create a module that acts as a singleton container - include a private instance variable and a public accessor property. optionally you can use a 'let' setter to allow the singleton to be 'replaced' with a new [static] class (using different constructor parameters - see #2,3). Use 'Let' for the setter, so you can assign the singleton without using 'set' ala OO languages
Private curStaticClass as StaticClass
Public Property Get CurrentStaticClass() As StaticClass
If curStaticClass Is Nothing Then Set curStaticClass = CreateStaticClass
Set CurrentStaticClass = curStaticClass
End Property
Public Property Let CurrentStaticClass(value As StaticClass)
If Not (curStaticClass Is Nothing) Then Set curStaticClass = Nothing
Set curStaticClass = value
End Property
6. To assign the singleton:
CurrentStaticClass = CreateStaticClass(parameters)
7. To use the singleton:
[value = ] CurrentStaticClass.MethodName(parameters)
That ("Public Shared") would only work in VB.Net.
There is no way to define Class Methods in VBA (or VB). I'd suggest to create a public function in a module.
You could try setting the VB_PredeclaredId
attribute of the class you wish to be static to True
. This creates a default instance of the class in much the same way that forms work in VBA (notice that you can refer to them directly without creating an instance. I know that this is not best practice but it is possible).
This means that you would have more of a singleton-style class, but it could serve your requirements...
You can't set this directly from the VBA IDE itself, however, you can perform the following steps:
1. Export the class you wish to make static to a folder.
2. Open the .cls
file you exported in your favourite text editor and change the
entry for VB_PredeclaredId
so that it reads VB_PredeclaredId = True
.
3. Save the file and re-import into VBA.
You should then be able to call your public methods on the class without having to instantiate the class. Bear in mind that the Initialize
method is only called the first time you execute a class method/access a class property, and Terminate
method is never called. Therefore you may wish to write your own constructor and also ensure you explicitly call the destructor if you need one.
Reference: UtterAccess.com Singleton Example
Reference: http://msdn.microsoft.com/en-us/library/ee199159.aspx
Bit late in the day but what the heck
There are no class or static methods in VB6/VBA. But you can explicity state the name of a module. You can't have a module and a class of the same name but you could call it something similar.
So I could have a class called Employee and a module called EmployeeUtil and then I can write:
Dim emp As Employee
Dim code As String
Set emp = EmployeeUtil.Create( "Smith", "John", 21-Feb-1988)
code = "123XY"
If EmployeeUtil.IsCodeValid( code) Then
emp.Code = code
Else
emp.Code = EmployeeUtil.DefaultCode
EndIf
Yes, the values are hard coded and the code handling should probably be under the property setter but that is not the point I'm trying to make. EmployeeUtil is essentially being a place holder for non-instance members.
You'll note that the Create method this way gives us a pseudo like constructor for the Employee class. All that function does is create an instance of Employee, assign the parameters via the property setters and then returns the instance. If your constructing instances of objects in a lot of places, then this can save a lot of code.