VBA中的类(静态)方法

我想知道,是否有可能在VBA中创build类方法。 通过类方法,我的意思是可以在没有类的对象的情况下调用的方法。 “静态”关键字在C ++和Java中有这个技巧。

在下面的例子中,我尝试创build一个静态工厂方法。

例:

'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' 

那(“公共共享”)只能在VB.Net中工作。

在VBA(或VB)中没有办法定义类方法。 我build议在模块中创build一个公共的function。

1.创build一个包含公共方法的普通类,您需要成为“静态”

2.在这个'静态'类中包含一个公共方法来初始化类中的[private]'static fields'(如果你愿意,它可以带参数)

3.创build一个模块作为一个工厂

 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.现在可以通过调用CreateStaticClass('parameters')来使用'static'类。MethodName('parameters')不需要像工厂方法那样初始化实例

5.(可选)如果你想强制单例实例,你可以创build一个充当单例容器的模块 – 包含一个私有实例variables和一个公共访问器属性。 可选地,你可以使用'let'setter来允许singleton被一个新的[static]类replace(使用不同的构造参数 – 参见#2,3)。 使用“Let”给setter,所以你可以不使用'set'ao OO语言来分配单例

 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.分配单身人士:

 CurrentStaticClass = CreateStaticClass(parameters) 

7.要使用单例:

 [value = ] CurrentStaticClass.MethodName(parameters) 

在一天晚些时候,但到底是什么

VB6 / VBA中没有类或静态方法。 但是你可以明确指出一个模块的名字。 你不能有一个模块和一个同名的类,但你可以把它叫做类似的东西。

所以我可以有一个名为Employee的类和一个名为EmployeeUtil的模块,然后我可以这样写:

  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 

是的,这些值是硬编码的,代码处理可能应该在属性设置器下,但这不是我想要做的。 EmployeeUtil本质上是非实例成员的占位符。

你会注意到,Create方法以这种方式给了我们一个Employee类的伪类似构造函数。 该函数所做的就是创build一个Employee实例,通过属性设置器分配参数,然后返回实例。 如果你在很多地方构build对象的实例,那么这可以节省很多代码。

您可以尝试将您希望为静态的类的VB_PredeclaredId属性设置为True 。 这样就创build了类的默认实例,就像VBA中的表单一样(注意,你可以直接引用它们而不需要创build一个实例,我知道这不是最佳实践,但它是可能的)。

这意味着你将有更多的单身风格的类,但它可以满足你的要求…

您不能直接从VBA IDE本身设置,但是您可以执行以下步骤:

1.将您希望制作静态的类导出到文件夹。

2.打开您最喜欢的文本编辑器中导出的.cls文件,并更改VB_PredeclaredId条目,使其读取VB_PredeclaredId = True

3.保存文件并重新导入到VBA中。

然后,您应该可以在类上调用您的公共方法,而无需实例化类。 请记住, Initialize方法仅在您第一次执行类方法/访问类属性时调用,并且永远不会调用Terminate方法。 因此,您可能希望编写自己的构造函数,并确保在需要时显式调用析构函数。

参考: UtterAccess.com单例子

参考: http : //msdn.microsoft.com/en-us/library/ee199159.aspx

AFAIK,最接近你可以得到(而不是那么接近)是使用一个“匿名”的实例,所以这样的事情:

 With New NotReallyStaticClass .PerformNotReallyStatic Method, OnSome, Values End With 

相似类的Instancing属性可用于静态类。 为其“GlobalMultUse”实例化属性必须指定。

静态类示例:

 ' Error Class in ClassInstancing ActiveDLL project Option Explicit Private m_errorID As Integer Private m_Description As String Public Property Get ErrorID() As Integer ErrorID = m_errorID End Property Public Property Let ErrorID(ByVal vNewValue As Integer) m_errorID = vNewValue End Property Public Property Get Description() As string Description = m_Description End Property Public Property Let Description(ByVal vNewValue As string) m_Description = vNewValue End Property Public Function Error() As Error Dim errorInstance As New ClassInstancing.Error With errorInstance .ErrorID = Me.ErrorID .Description = Me.Description End With Set Error = errorInstance End Function Public Sub RaiseError(ByVal pErrorID As Integer, ByVal errorSource As String, ByVal errorDesc As String) Err.Raise pErrorID, errorSource, errorDesc End Sub Public Sub ShowError() MsgBox "Error ID: " & CStr(Me.ErrorID) & vbCrLf & _ "Desc: " & Me.Description End Sub 

GlobalMultiUse Instancing属性将类指定为一组…

在其他标准EXE项目中使用此全局(静态!)类:

 Private Sub Command1_Click() ClassInstancing.Description = "Sample-1 error using !" ClassInstancing.ErrorID = 9990 'Dim multiuseClass As ClassInstancing.Error 'Set multiuseClass = ClassInstancing.Error MsgBox ClassInstancing.Error.ErrorID & vbCrLf & ClassInstancing.Error.Description, vbInformation, "Sample Usage 1" ClassInstancing.Description = "Sample-2 error using !" ClassInstancing.ErrorID = 1110 ClassInstancing.ShowError End Sub 

最后,MSDN中的注释((MSDN Library Visual Studio 6.0,“Instancing Property”)):

GlobalMultiUse。 与MultiUse类似,只需添加一个:可以调用该类的属性和方法,就好像它们只是全局函数一样。 没有必要先显式创build一个类的实例,因为会自动创build一个实例。

虽然这不是严格的问题本身的答案,但我想指出,应该避免Mike Woodhouse的解决scheme。 每次创build对象的新实例都会导致性能下降,并且不能解决原始问题 – 它不会创build静态对象,也不会提供静态方法。

由于VBA没有类函数的概念,最接近的就是在模块中使用函数。

至于工厂方法,我build议创build一个模块,将Factory附加到模块正在创build的类的名称上。 就像是:

 'Module PersonFactory Option Explicit Public Function Create(ByVal sName As String) As Person 'Code here End Function 

这远不是其他语言的静态方法概念,但至less它提供了一个可以在项目中使用的模式。

你必须先声明p2,然后才能使用Set,如下所示:

作为人昏暗的p2

一旦你这样做,你必须使用标准的赋值来replaceSet语句:p2 = Person.Create(“Bob”)

在function:删除“设置”关键词…这也可能是一个错误的来源。

我是盲目的,但从逻辑上来说,这似乎应该工作。 我在VBA中使用Class模块是新手,但它们与使用VB.Net属性并没有太大的区别。