限制类模块中Collection的类型

| 我在一个类模块中有一个集合。我想将“可添加”的对象类型限制为该集合,即,集合只能接受一种给定类型的对象,而不能接受其他任何对象。 有什么方法可以强制添加到集合中的对象类型? 据我所知,没有内置的方法可以做到这一点。那么,解决方案是否将这个集合设为私有,并为通常可用于集合的方法(即
Add
Remove
Item
Count
)构建包装函数? 我有点讨厌不得不编写3个包装函数,这些包装函数没有添加任何功能,只是为了能够向some0ѭ方法添加某种类型强制。但是,如果这是唯一的方法,那么那是唯一的方法。     
已邀请:
无法避免包装函数。这只是VBA使用的“通过遏制/委托进行专业化”模型中固有的。 不过,您可以构建一个“自定义集合类”。您甚至可以使用
For...Each
使其迭代,但这需要离开VBA IDE并直接编辑源文件。 首先,请参阅旧的《 Visual Basic 6.0程序员指南》中的“创建自己的集合类”部分: http://msdn.microsoft.com/zh-CN/library/aa262340(v=VS.60).aspx 在stackoverflow上,还有一个答案描述了同一件事: vb6等效于list 但是,这些是针对VB6(而非VBA)编写的。在VBA中,您无法在IDE中执行“过程属性”部分。您必须将类模块导出为文本,然后使用文本编辑器将其添加。 Dick Kusleika的网站Excel的每日剂量(您可能知道Dick是常规的stackoverflow贡献者)在Rob van Gelder的帖子中显示了如何执行此操作: http://www.dailydoseofexcel.com/archives/2010/07/04/custom-collection-class/ 在您的情况下,麻烦解决-每个“自定义集合”类都需要自己的模块-可能不值得。 (如果您对此只有一种用途,并且又埋在另一个类中,则可能会发现自己不想公开所有
Collection
的功能。)     
这就是我所做的。我喜欢@jtolle所指的Rob van Gelder的示例,但是为什么我应该满足于制作一个“自定义集合类”,该类只能永远接受一种特定的对象类型(例如(7ѭ)?正如@jtolle指出的那样,这很烦人。 取而代之的是,我推广了这个想法,并创建了一个新的类
UniformCollection
,它可以包含任何数据类型-只要在任何给定的
UniformCollection
实例中所有项目都是同一类型。 我添加了一个私有Variant,它是给定实例ѭ8可以包含的数据类型的占位符。
Private mvarPrototype As Variant
在创建“ 8”实例之后,使用它之前,必须通过指定它将包含的数据类型来对其进行初始化。
Public Sub Initialize(Prototype As Variant)
    If VarType(Prototype) = vbEmpty Or VarType(Prototype) = vbNull Then
        Err.Raise Number:=ERR__CANT_INITIALIZE, _
            Source:=TypeName(Me), _
            Description:=ErrorDescription(ERR__CANT_INITIALIZE) & _
                TypeName(Prototype)
    End If
    \' Clear anything already in collection.
    Set mUniformCollection = New Collection
    If VarType(Prototype) = vbObject Or VarType(Prototype) = vbDataObject Then
        \' It\'s an object. Need Set.
        Set mvarPrototype = Prototype
    Else
        \' It\'s not an object.
        mvarPrototype = Prototype
    End If
    \' Collection will now accept only items of same type as Prototype.
End Sub
然后,Add方法将只接受与Prototype类型相同的新项目(无论是对象还是原始变量……尚未使用UDT进行测试)。
Public Sub Add(NewItem As Variant)
    If VarType(mvarPrototype) = vbEmpty Then
        Err.Raise Number:=ERR__NOT_INITIALIZED, _
            Source:=TypeName(Me), _
            Description:=ErrorDescription(ERR__NOT_INITIALIZED)
    ElseIf Not TypeName(NewItem) = TypeName(mvarPrototype) Then
        Err.Raise Number:=ERR__INVALID_TYPE, _
            Source:=TypeName(Me), _
            Description:=ErrorDescription(ERR__INVALID_TYPE) & _
                TypeName(mvarPrototype) & \".\"
    Else
        \' Object is of correct type. Accept it.
        \' Do nothing.
    End If

    mUniformCollection.Add NewItem

End Sub
其余部分与示例大致相同(加上一些错误处理)。糟糕的RvG并没有完全解决!更糟糕的是,Microsoft没有将这种功能作为内置功能包含在内...     
我几乎执行了Jean-FrançoisCorbett的相同代码,但由于某些原因无法正常工作,因此我进行了修改。
Option Explicit

Public pParametro As String
Private pColecao As New Collection

Public Sub Inicializar(ByVal parametro As String)
    pParametro = parametro
End Sub

Public Sub Add(NewItem As Object)
If TypeName(NewItem) <> pParametro Then
    MsgBox \"Classe do objeto não é compatível à coleção\"
Else
    pColecao.Add NewItem
End If
End Sub

Public Property Get Count() As Long
  Count = pColecao.Count
End Property

Public Property Get Item(NameOrNumber As Variant) As Variant
  Set Item = pColecao(NameOrNumber)
End Property

Sub Remove(NameOrNumber As Variant)
  pColecao.Remove NameOrNumber
End Sub
然后,当我想从CCollection创建一个实例时,就像下面的代码:
    Set pFornecedores = New CCollection
    pFornecedores.Inicializar (\"CEmpresa\")
其中CEmpresa是我想要的对象的类类型     
是。解决方案是将您的集合设为私有,然后使公共包装器函数添加,删除,获取项目和计数等。 编写附加代码似乎很麻烦,但是封装这样的集合是一种更可靠的解决方案。     

要回复问题请先登录注册