本主题将继续讨论在“公有集合示例:稻草盖的房子”和“私有集合示例:树枝盖的房子”开始讨论的代码示例。在开始本主题之前,最好阅读那些主题。
实现集合的最强健方法,是使其成为类模块。与前面的示例相比较,将对象创建的所有代码移到集合类中,这就较好符合了面向对象程序设计的原则。
该例使用了跟前面的例子同样的窗体和同样的 Employee 类模块。插入新的类模块,并将其 Name 属性设置为“Employees”。将下面的声明和代码插入到这个新的类模块中。
Option Explicit
Private mcolEmployees As New Collection
Employees 类的 Add、Count 以及 Delete 方法,本质上都跟旧的 SmallBusiness 类中的那些方法是相同的。可以简单地把它们从 SmallBusiness 类模块中删除,然后粘贴到 Employees 类模块中,并更改一下它们的名字。
名字都可以更改,因为不再需要将 EmployeeAdd,比如说,跟 CustomerAdd 区别开来。所实现的每个集合类都有自己的 Add 方法。
'Employees
集合类的方法。Public Function Add(ByVal Name As String, _
ByVal Salary As Double) As Employee
Dim empNew As New Employee
Static intEmpNum As Integer
'
用With
语句,使代码更快,也更简洁'
(.ID
相对empNew.ID)
。With empNew
'
为新雇员产生一个唯一的ID
。intEmpNum = intEmpNum + 1
.ID = "E" & Format$(intEmpNum, "00000")
.Name = Name
.Salary = Salary
'
将Employee
对象引用添加到集合中,'
用ID
属性作为键。mcolEmployees.Add empNew, .ID
End With
'
为新的Employee
返回一个引用。Set Add = empNew
End Function
Public Function Count() As Long
Count = mcolEmployees.Count
End Function
Public Sub Delete(ByVal Index As Variant)
mcolEmployees.Remove Index
End Sub
SmallBusiness 对象的 Employees 方法变成了集合类中的 Item 方法。为了通过索引或者键来检索成员,它仍然委派 Collection 对象为代表。
'Employees
集合类的方法。Public Function Item(ByVal Index As Variant) _
As Employee
Set Item = mcolEmployees.Item(Index)
End Function
可以在这里添加一个很好的技巧。通过将 Item 设置为 Employees 类的缺省方法,就得到了为 Employees("E00001")
编写代码的能力,就象用 Collection 对象做的一样。
要使 Item 成为缺省的属性,请按照以下步骤执行:
注意 一个类只能有一个缺省成员(属性或者方法)。
伴随着强健性而来的,是重新获得了 For Each ... Next。通过添加下面的方法,可以再一次将所有工作委派给 Collection 对象:
'NewEnum
必须返回一个集合的枚举算子的IUnknown
接口。Public Function NewEnum() As IUnknown
Set NewEnum = mcolEmployees.[_NewEnum]
End Function
委派给 Collection 对象的最重要的东西是它的枚举算子。枚举算子是一个小对象,该对象知道如何遍历集合中的各项。不能用 Visual Basic 来书写枚举算子对象,因为 Employees 类是基于 Collection 对象的,可以返回 Collection 对象的枚举算子—它自然知道如何枚举 Collection 对象所保存的各项。
包围 Collection 对象的 _NewEnum 方法的方括号是必要的,这是因为方法名前面的下划线。前面的这个下划线是一个约定,它指明该方法是隐藏在类型库中的。不能把自己的方法命名为 _NewEnum,但是可以把它隐藏在类型库中,并将 For Each ... Next 所需要的过程 ID 赋给它。
要隐藏 NewEnum 方法,并将所需的过程 ID 赋给它,请按照以下步骤执行:
重点 为了使自己的集合类使用 For Each ... Next 来工作,必须提供有正确过程标识符的隐藏 NewEnum 方法。
到现在为止,SmallBusiness 类中还只有相当少的代码。为了取代所删除了的 Collection 对象和所有方法,有新的声明和只读属性:
Option Explicit
Private mEmployees As New Employees
Public Property Get Employees() As Employees
Set Employees = mEmployees
End If
这需要简单解释一下。假设曾经省略了 Property Get,那么可以简单地声明 Public Employees As New Employees
。
只要没有人犯什么错误,每件事物都将很好地工作,但是如果偶然编写代码为 Set sbMain.Employees = Nothing
,将会发生什么情况?对,Employees 集合将被撤消。若是将 Employees 设置为只读属性,则可以避免这种可能性。
窗体模块的代码跟前面示例中的非常类似。可用模块级相同的声明,而且“关闭”按钮的 Click 事件也是同样的。
在大多数事件过程中的唯一改动是:用 Employees 集合对象的新方法取代 SmallBusiness 类的旧方法:
Private Sub cmdEmployeeAdd_Click() sbMain.Employees.Add txtName.Text, txtSalary.Text txtName.Text = "" txtSalary.Text = "" cmdListEmployees.Value = True End Sub Private Sub cmdEmployeeDelete_Click() '
检查一下,以确保有雇员被选中。If lstEmployees.ListIndex > -1 Then
'
前六个字符是ID
。sbMain.Employees.Delete _
Left(lstEmployees.Text, 6)
End If
cmdListEmployees.Value = True
End Sub
Private Sub cmdListEmployees_Click()
Dim emp As Employee
lstEmployees.Clear
For Each emp In sbMain.Employees
lstEmployees.AddItem emp.ID & ", " & emp.Name _
& ", " & emp.Salary
Next
End Sub
注意,又可以用 For Each ... Next 来列出雇员了。
运行该工程,并验证每件事物都能正常工作。这次“有问题”按钮没有任何代码,因为封装已经消除了问题。
详细信息 为了得到关于背景集合的信息,请阅读“Visual Basic 集合对象”和“Visual Basic 集合”。
在专业版和企业版中,包括了 Class Builder 实用工具,该实用工具可以创建集合类。
稻草盖的房子、树枝盖的房子以及砖块盖的房子的示例课程部分,在下面的“好的面向对象程序设计的优点”中作了总结。