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属性并没有太大的区别。