答:VB的类创建助手(Class Builder Wizard)能为你创建一个自定义类,当然真正的程序员不会使用这些助手(或者说捡这个便宜)。幸运的是创建一个自定义集合不是特别难,就像你将在本文中看到的一样。但是首先,我们还是先回头定义一个自定义集合,再回答你问题的第二部分。
VB Collection对象可自我管理,它们能在你加入和删除其中项目时自动增大和减小。利用这些关键特征的优势,并在加入对象的时候指定String键值,你就能以相对较快的速度从一个集合中检索到任意的对象。所以集合提供了一种在应用程序里组织和存储对象的简单方法。
你可以创建一个公共集合(public collection)并按需加入对象。这种方法的问题是,既然你把集合暴露在外,你就无法控制加入的东西。假设你使用一个集合来存储一些cFoo对象,而有人错误的加入了cBar对象。以后任何只期望在其中找到cFoo对象的代码,在发现了cBar对象后极有可能出现异常反应。
使用公共集合的另一个问题是,你集合中所存储的对象必须是公共的,并且可由集合的客户代码创建。也就是说,cFoo类必须在它能够被加入到集合以前由程序员明确无误地建立好。例如,你不能使用客户提供的参数在Add方法中创建cFoo对象,不能为任何可选的参数提供缺省的值。你也不能在集合中创建和保存另一个新对象,这个对象自身包含了cFoo对象及其相关数据。换句话说,你的执行不能对用户代码隐藏。
假如VB能支持执行的继承,那么我们通过创建一个Collection的子类并且使用我们自己的只能接受cFoo对象的方法取代Add方法就能解决第一个问题。我们自然不能那样做,至少在“经典VB”里不行。但是我们可以通过创建一个类来伪造一个,这个类将集合所有预期的方法和属性暴露在外,并包含了一个用来存储可以被通过的任何对象的私有集合(private collection)。
这事实上是一个完美合法的面向对象的技巧,叫做合成,这就是我对Listing A中的cFooCollection所做的事,它向一个类似集合的类提供了直接受cFoo对象的Add方法。cFooCollection类和集合类并不兼容,这意味着你不能把它用在需要集合类型参数的替换符和函数上。除了创建时要花点儿外的功夫外,这真的就是它唯一的缺点。
我们可以改变Listing A里的代码以解决第二个问题。只要把Add方法更改为接受创建新的cFoo对象所需要的一切参数就行了,而不是创建cFoo对象自己,见Listing B。