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.