VBA中的类(静态)方法

时间:2008-12-28 12:03:39

标签: vba static

我想知道,是否可以在VBA中创建类方法。通过类方法,我的意思是可以在没有类的对象的情况下调用的方法。 'static'-keyword在C ++和Java中实现了这一技巧。

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

示例:

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

8 个答案:

答案 0 :(得分:40)

1。创建一个包含您需要“静态”的公共方法的普通类

2. 包含一个公共方法[在此'静态'类中]初始化类中的[private]'静态字段'(如果您愿意,可以使用参数)

3. 创建模块作为工厂

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'类。方法名称('参数') 没有必要初始化实例,因为它是由工厂方法

完成的

<强> 5。 (可选)如果要强制执行单例实例,可以创建充当单例容器的模块 - 包括私有实例变量和公共访问器属性。可选地,您可以使用'let'设置器来允许使用新的[static]类“替换”单例(使用不同的构造函数参数 - 请参阅#2,3)。使用'Let'作为setter,这样你就可以在不使用'set'ala 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)

答案 1 :(得分:30)

那个(“公共共享”)只能在VB.Net中使用。

无法在VBA(或VB)中定义类方法。我建议在模块中创建一个公共函数。

答案 2 :(得分:17)

您可以尝试将要保持静态的班级的VB_PredeclaredId属性设置为True。这创建了类的默认实例,其方式与在VBA中表单工作的方式非常相似(请注意,您可以直接引用它们而无需创建实例。我知道这不是最佳实践,但它是可行的。)

这意味着您将拥有更多单身式的课程,但它可以满足您的要求......

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

1。将要制作静态的课程导出到文件夹。

2。打开您在自己喜欢的文字编辑器中导出的.cls文件并更改     VB_PredeclaredId的条目,使其显示为VB_PredeclaredId = True

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

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

参考:UtterAccess.com Singleton Example

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

答案 3 :(得分:8)

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

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类提供了一个类似伪的构造函数。该函数所做的就是创建一个Employee实例,通过属性setter分配参数,然后返回实例。如果你在很多地方构建对象的实例,那么这可以节省很多代码。

答案 4 :(得分:4)

AFAIK,你能得到的最接近的(并不是那么接近)是使用“匿名”实例,所以像这样:

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

答案 5 :(得分:2)

虽然这不是问题本身的严格答案,但我想指出应该避免Mike Woodhouse的解决方案。每次创建一个对象的新实例都是性能损失而且它确实无法解决原始问题 - 它不会创建静态对象,也不会提供静态方法。

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

对于工厂方法,我建议创建一个模块,在模块创建的类的名称后附加单词Factory。类似的东西:

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

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

答案 6 :(得分:1)

类似类的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类似,只增加一个:可以调用类的属性和方法,就好像它们只是全局函数一样。没有必要首先显式创建类的实例,因为将自动创建一个实例。

答案 7 :(得分:-2)

你必须在使用Set之前声明p2,如下所示:

dim p2 as Person

执行此操作后,您必须使用标准作业替换Set语句: p2 = Person.Create(“Bob”)

在功能中: 删除“设置”关键字...这也可能是错误的来源。

我是盲目飞行的,但从逻辑上看,这似乎应该有效。我不熟悉在VBA中使用类模块,但它们与使用VB.Net属性没什么不同。