【问题标题】:Class (Static) Methods in VBAVBA 中的类(静态)方法
【发布时间】:2010-09-28 14:36:45
【问题描述】:

我想知道是否可以在 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'

【问题讨论】:

  • 这并没有涵盖这个问题的重点,即类方法,但是类方法的大多数用途不会被返回到 person 类的另一个实例的方法所涵盖?例如在模块中,您将拥有: Dim person As new Person: Set person = person.Create("Bob")。类中的 Create 方法如下: Public Function Create(name As String) As Person: Dim p As Person: Set p = New Person: p.name = name: Set create = p: End Function。 IE。一旦你初始化了一个类的“处理程序”实例,它就可以用来返回它自己的类的其他实例。
  • @Cor_Blimey:你描述的技术肯定会奏效。然而,问题的关键在于不需要“处理程序”实例。

标签: vba static


【解决方案1】:

您可以尝试将您希望为静态的类的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

【讨论】:

  • 出色的解决方案,感谢您提供精确的 VBA 规范参考。这应该是最佳答案,我认为只是落后,因为它是在(当前)最佳答案之后的 4 年。我推荐。
  • 这是在 VBA 中实现“静态”类行为的正确方法
【解决方案2】:

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' 设置器来允许将单例“替换”为新的 [静态] 类(使用不同的构造函数参数 - 参见 #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)

【讨论】:

  • 我正在寻找如何在 excel vba 中编写单例。谷歌让我得到了你的答案。谢谢。
  • 所以如果我只想要单例(初始化并不重要),那么我使用 5) ?
  • 使用您的解决方案(如果我理解良好的话),我建议here 一个基本示例,如何定义实例的“静态”计数器,即在每个 New 处 +1。
【解决方案3】:

类似类的实例化属性可用于静态类。必须指定它的实例化属性“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 类似,但有一个补充:可以像调用全局函数一样调用类的属性和方法。没有必要首先显式创建类的实例,因为会自动创建一个。

【讨论】:

  • 这仅在 VB6 中可用,在 VBA 中不可用。
【解决方案4】:

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

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

【讨论】:

【解决方案5】:

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

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

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

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

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

【讨论】:

    【解决方案6】:

    今天有点晚了,但到底是什么

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

    【讨论】:

      【解决方案7】:

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

      将 p2 调暗为 Person

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

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

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

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          猜你喜欢
          • 2011-01-17
          • 2011-07-11
          • 1970-01-01
          • 2012-06-24
          • 1970-01-01
          • 2010-11-02
          • 1970-01-01
          • 2012-04-19
          • 1970-01-01
          相关资源
          最近更新 更多