Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VBA中的类(静态)方法_Vba_Static - Fatal编程技术网

VBA中的类(静态)方法

VBA中的类(静态)方法,vba,static,Vba,Static,我想知道,是否有可能在VBA中创建类方法。我所说的类方法是指不需要类的对象就可以调用的方法。“静态”关键字在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 say

我想知道,是否有可能在VBA中创建类方法。我所说的类方法是指不需要类的对象就可以调用的方法。“静态”关键字在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'
“公共共享”只能在VB.Net中使用


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

AFAIK,最接近的方法是使用“匿名”实例,如下所示:

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

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

作为人

执行此操作后,必须使用标准赋值替换Set语句: p2=个人创建(“Bob”)

在函数中: 删除“Set”关键字…这也可能是错误的来源


我在瞎飞,但从逻辑上看,这应该行得通。我不太熟悉在VBA中使用类模块,但它们与使用VB.Net属性没有太大区别。

有点晚了,但这又是怎么回事

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
是的,这些值是硬编码的,代码处理可能应该在属性setter下进行,但这不是我想说的重点。EmployeeUtil本质上是非实例成员的占位符


您将注意到,通过这种方式创建方法为Employee类提供了一个伪类构造函数。该函数所做的只是创建Employee的实例,通过属性设置器分配参数,然后返回实例。如果您在很多地方构造对象实例,那么这可以节省大量代码。

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

2.包括一个公共方法[在此“静态”类中],用于初始化类中的[private]“static fields”(如果愿意,可以使用参数)

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

5。(可选)如果要强制执行单例实例,可以创建一个充当单例容器的模块-包括一个私有实例变量和一个公共访问器属性。或者,您可以使用“let”setter来允许使用新的[static]类“替换”单例(使用不同的构造函数参数-请参见#2,3)。对setter使用“Let”,这样就可以在不使用“set”语言的情况下分配单例

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)
[value = ] CurrentStaticClass.MethodName(parameters)
7.要使用单例:

CurrentStaticClass = CreateStaticClass(parameters)
[value = ] CurrentStaticClass.MethodName(parameters)

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

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

至于工厂方法,我建议创建一个模块,将单词factory附加到该模块正在创建的类的名称中。比如:

'Module PersonFactory
Option Explicit

Public Function Create(ByVal sName As String) As Person

    'Code here

End Function

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

类似类的实例化属性可在静态类中使用。必须指定其“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
GlobalMulti使用实例属性将类指定为一组

此全局(静态!)类在其他standart 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库Visual Studio 6.0,“实例化属性”)中的注释:

全球通用。类似于MultiUse,还有一点:类的属性和方法可以像调用全局函数一样调用。没有必要先显式地创建类的实例,因为会自动创建一个实例


您可以尝试将希望静态的类的
VB\u PredeclaredId
属性设置为
True
。这将创建类的默认实例,其方式与VBA中窗体的工作方式大致相同(请注意,您可以直接引用它们,而无需创建实例。我知道这不是最佳做法,但也是可能的)

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

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

1。将要使其成为静态的类导出到文件夹中

2.打开您在喜爱的文本编辑器中导出的
.cls
文件,然后更改
VB\u PredeclaredId
的条目,以便它读取
VB\u PredeclaredId=True

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

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

参考:


参考资料:

我正在寻找如何在