Excel VBA 编程基础 -- 类与对象(五)
在 Excel 的对象模型中,有对象类,如 Application、Workbook、Worksheet 等对象,也有集合类,最典型的如 Workbooks、Worksheets 等等。虽然微软的文档中称 Workbooks、Worksheets 为对象(object),但实际上这些都是集合:Workbooks 包含当前所有打开的工作簿,而 Worksheets 则包含指定工作簿或当前工作簿中所有的工作表。当然,集合也是对象,在这个意义上,将 Workbooks、Worksheets 等称为对象自然也是合理的。- Delete:方法,删除集合中元素,有时也称为 Remove
上文我们实现了 CStudent 对象类,并利用这个类读取了学生成绩表,并将学生成绩表装在了 myA 数组中。现在我们来实现 CStudents 集合类,然后将学生成绩表装在 CStudents 的集合中。例1. 利用 CStudents 集合对象来读取学生成绩表图1 利用 CStudents 集合对象来读取学生成绩表关于函数 BuildStudentObject,请参见上一篇文章。前面我们说,集合对象要有 Item 属性,该属性接受一个整数索引,返回集合中该索引所对应的对象,并且一般集合对象都将 Item 属性实现为默认属性(default property),正如图中所示,CStudents 对象的 Item 属性也是默认属性。所谓默认属性(default property),就是不需要明确指定名字就可以访问的属性。如下面的代码所示:Dim cs As CStudentsDim cso As CStudent...Set cso = cs(0) ' cs.Item(0)
z在这段代码中,因为 Item 是 CStudents 的默认属性,所以访问 cs(0) 就相当于访问 cs.Item(0)。默认属性给我们带来很多方便,譬如,因为 Value 是 Range 的默认属性,所以访问 Range("A1") 就相当于访问 Range("A1").Value。CStudents 集合类除实现了默认属性,还实现了 Add 和 Delete 方法,用来向集合中添加元素和删除集合中的元素。其中,element 是类型为 CStudent 的对象。CStudents.Delete 方法的一般格式为:其中,index 是类型为 Long 的整数索引。如果索引超出了集合中元素索引的范围,则 Delete 什么使也不做。CStudents 还实现了只读属性 Count,作用是返回当前集合中元素总数。有了 Count,可以将 Delete 方法中的 index 参数的范围表示为:说完了 CStudents 的作用,下面来看看 CStudents 集合类是如何实现的。由图可见,我们在 CStudents 集合类内部使用了数组来保存集合元素。数组在初始化事件中初始化。值得指出的是,数组并不是性能最优的实现,因为在删除元素时,被删除元素之后的所有元素(所有索引 > index 的元素)都要前移一个位置(index + 1 位置的元素前移到 index 位置),以填补被删除元素的空缺。对于大型集合类,数组元素的移动成本是很高的。另外,数组空间的增减(增加或删除元素时的 Redim),在上图中也不是性能最优的,还可以有更优的实现。单纯就 Item 来说,其实现其实很简单,如图所示,首先判断参数 index 是否超出范围,如果超出范围,则返回 Null,否则返回该 index 对应的元素。但这样实现的 Item 并不是默认属性,要实现默认属性,需要作特殊处理。首先,将 CStudents 类导出到文件 CStudents.cls。其次,移除 VBE 中的 CStudents 类。然后,打开记事本,编辑导出的 CStudents.cls,修改 Item 属性。如下图所示:对照图3 和图2,可以看出,图3 多了两行内容,正是正两行内容,是使得 Item 属性成为默认属性的关键,尤其是:Attribute Item.VB_UserMemId = 0最后,将修改后的 CStudents.cls 导入回我们的项目。经过上面的一系列步骤,Item 就成为 CStudents 集合类的默认属性了。- 这两行 Attribute 是 VB/VBA 的内部信息,无法在 VBE 的代码窗口中直接输入。
- Property 和 Attribute:这两个英文词对应的中文意思基本相同,其实英文意思也差不多。但在 OOP 语境中,Property 都用来作为对象的外部可访问性质,Attribute 则用来作为内部说明性质的用途。
CStudents 集合类还可以做诸多优化,下次再讲。