gpt4 book ai didi

vba - 如何将类名作为参数传递?

转载 作者:行者123 更新时间:2023-12-03 15:48:03 25 4
gpt4 key购买 nike

我想创建一个函数,它接受一个类示例/类名并返回该类的一定数量的示例的集合,初始化并填充。到目前为止,我已经提出了这个解决方案:

Function getCollectionObj(className as string) As Collection

Dim obj As Variant
Dim result As Collection
Dim objType As String
Dim I

For I = 1 To 5

'selecting the type of a class based on string name
Select Case className
Case "Cls1"
Set obj = New Cls1
Case "Cls2"
Set obj = New Cls2
Case "DocumentStart"
Set obj = New Cls3
End Select
'some code handling the exemplar of the object.

result.add obj
Next I
Set getCollectionObj = result
End Function
问题是我必须明确地将每个类放入 select case并且代码每次都必须选择和声明 cerain 类,即使集合中的所有对象都应该是同一类的示例。我该如何改进它?
编辑:我的测试代码(给出“object required error”)
主要模块:
Private Function getCollectionObj(ByVal factory As IObjectFactory) As Collection
Dim I
For I = 1 To 5
result.Add factory.Create
Next I
End Function

Sub test()
Dim var As Object
Set var = getCollectionObj(New Class1ObjectFactory)
End Sub
IObjectFactory 类:
Option Explicit
Public Function Create() As Object

End Function
Cls1Factory 类(选择函数时右侧下拉菜单显示“创建”):
Option Explicit
Implements IObjectFactory

Private Function IObjectFactory_Create() As Object
' "Object required" error here
Set IObjectFactory_Create = New Cls1
End Function
Cls1类:
Option Explicit
Public I As String

最佳答案

理想情况下,您不需要(回答标题中的问题)——例如,当类被重命名时,您的代码不会静默中断。
有一种更好的方法,它可以在出现问题时立即为您提供编译时错误,并且可以很好地与静态代码分析和重构工具配合使用,例如 Rubberduck - 完全公开,那是我的网站,我管理 Rubberduck 开源项目。
您可以通过定义抽象工厂接口(interface)来形式化创建类实例的任务。添加一个新的类模块,命名为IObjectFactory :

Option Explicit
Public Function Create() As Object
End Function
现在添加一个新的类模块,命名为 Cls1Factory并使其实现抽象工厂接口(interface):
Option Explicit
Implements IObjectFactory

Private Function IObjectFactory_Create() As Object
Set IObjectFactory_Create = New Cls1
End Function
添加一个新的类模块,命名为 Cls2Factory并使其也实现抽象工厂接口(interface):
Option Explicit
Implements IObjectFactory

Private Function IObjectFactory_Create() As Object
Set IObjectFactory_Create = New Cls2
End Function
添加另一个可以创建 Cls3 的实现实例,称之为 Cls3Factory .
然后按如下方式更改函数的签名:
Public Function getCollectionObj(ByVal factory As IObjectFactory) As Collection
现在整个 Select Case block 变成这个单一的语句:
result.Add factory.Create
用于执行此操作的调用代码:
Set things1 = getCollectionObj("Cls1")
Set things2 = getCollectionObj("Cls2")
Set things3 = getCollectionObj("Cls3")
现在需要这样做:
Set things1 = getCollectionObj(New Cls1Factory)
Set things2 = getCollectionObj(New Cls2Factory)
Set things3 = getCollectionObj(New Cls3Factory)
该函数现在可以创建您想要的任何类的 5 个实例的集合,而无需对其进行任何修改:如果您需要支持一个新类,只需为其实现一个新工厂,然后将其作为参数传递给函数。

回复:编辑
Rubberduck 的静态代码分析可以帮助您避免大量陷阱,就像您编辑的片段中的陷阱一样:未分配函数返回值,在初始化之前访问结果变量等:
OP's revision 2 code under ducky scrutiny
“需要对象”错误由其根本原因发出信号,此处以级联顺序导致此特定错误:
  • 'Module1' 中未指定'Option Explicit'。
  • 未声明局部变量“结果”。
  • 变量“结果”已使用但未分配。
  • Option Explicit未指定允许代码以 result 执行没有被宣布。由于它没有被声明,它被分配为 Variant/Empty直到它被分配......除非它永远不会,并且当成员调用( .Add )暂时针对该变体进行时,那是 VBA 在运行时尖叫并说“需要对象”,因为需要一个对象该成员调用有效。但是 VBA 看到的只是 Variant/Empty它只是在现场创建的指针。
    .Create 之后引发运行时错误。工厂方法调用返回,但在返回的对象作为参数传递给意外后期绑定(bind) .Add 之前成员(member)电话。执行未进入 .Add方法,VBA 没有成功取消引用 Collection来自 result 的对象多变的;但是因为调试器不允许我们单步执行操作符,所以当我们单击“DEBUG”时,我们会返回失败的语句,以及整个 result.Add factory.Create语句被突出显示(而不是 result.Add 调用,这是实际失败的操作)。
    因为在同一行上有两条语句,所以调试器并不完全处于它现在应该处于的确切状态。如果我们按下 F8,我们将被带回工厂方法,如果我们没有意识到发生了什么,那么很容易让调试器将我们引入歧途,从而调查一个完全正常的执行路径。
    将语句分开:
    Dim o As Object
    Set o = factory.Create '<~ no problem here!

    result.Add o '<~ object required
    现在调试器进入中断模式,并突出显示正确的失败语句。
    为了完整起见,工作代码:
    Option Explicit

    Public Sub test()
    Dim var As Collection
    Set var = getCollectionObj(New Class1ObjectFactory)
    Debug.Print var.Count
    End Sub

    Private Function getCollectionObj(ByVal factory As IObjectFactory) As Collection
    Dim result As Collection
    Set result = New Collection
    Dim I As Long
    For I = 1 To 5
    result.Add factory.Create
    Next I
    Set getCollectionObj = result
    End Function

    关于vba - 如何将类名作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63908189/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com