48

我想知道是否可以在 VBA 中创建类方法。类方法是指可以在没有类对象的情况下调用的方法。'static' 关键字在 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'
4

8 回答 8

46

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

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

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').MethodName('parameters') 来使用“静态”类,不需要初始化实例,因为这是通过工厂方法完成的

5.(可选)如果您想强制执行单例实例,您可以创建一个充当单例容器的模块 - 包括一个私有实例变量和一个公共访问器属性。可选地,您可以使用 'let' setter 来允许用新的 [static] 类“替换”单例(使用不同的构造函数参数 - 参见 #2,3)。使用 'Let' 作为设置器,因此您可以在不使用 '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)
于 2010-11-16T17:19:00.553 回答
29

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

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

于 2008-12-28T12:36:48.323 回答
28

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

这意味着您将拥有更多的单例类,但它可以满足您的要求......

您不能直接从 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

于 2014-07-04T12:45:44.690 回答
9

有点晚了,但到底是什么

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 实例,通过属性设置器分配参数,然后返回该实例。如果你在很多地方构造对象的实例,那么这可以节省很多代码。

于 2009-08-27T05:15:16.943 回答
4

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

With New NotReallyStaticClass
    .PerformNotReallyStatic Method, OnSome, Values
End With
于 2008-12-28T16:29:23.483 回答
2

虽然这并不是对问题本身的严格回答,但我想指出应该避免使用 Mike Woodhouse 的解决方案。每次创建一个对象的新实例都会影响性能,而且它实际上并没有解决原来的问题——它不创建静态对象,也不提供静态方法。

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

至于工厂方法,我建议创建一个模块,并在模块正在创建的类的名称后附加工厂一词。就像是:

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

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

于 2011-09-08T03:59:41.367 回答
1

类似类的实例化属性可用于静态类。必须指定它的实例化属性“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')):

全球多用途。与 MultiUse 类似,但增加了一点:类的属性和方法可以像简单的全局函数一样被调用。没有必要首先显式创建类的实例,因为会自动创建一个。

于 2011-12-07T01:28:34.073 回答
-3

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

将 p2 调暗为 Person

完成此操作后,您必须使用标准赋值替换 Set 语句: p2 = Person.Create("Bob")

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

我瞎了眼,但从逻辑上讲,这似乎应该可行。我是在 VBA 中使用类模块的新手,但它们与使用 VB.Net 属性并没有太大区别。

于 2009-02-19T12:12:45.947 回答