Debug.PrintcolFiles.Item(1).Size
图1(左)VBACollection对象可以容纳任何类型的对象
图2(右)创建一个Collection类来防止不想要的对象进入集合
PrivatepcolFilesAsNewCollection
Createanewinstanceofanobject.
DimobjFileAsNewFile
objFile.Path=”C:AUTOEXEC.BAT”
AddtoaCollectionobject.
colFiles.AddobjFile,objFile.ShortName
应用Collection类,应用程序调用该类的Add方法,传递任何必需的信息。请将先前的代码与Files类的Add方法做一比较:
WithaCollectionclass,theapplicationcallstheAddmethodoftheclass,passinganyrequiredinformation.ContrastthepreviouscodewiththeAddmethodoftheFilesclass:
PublicFunctionAdd(PathAsString)AsFile
DimobjFileAsFile
CreatethenewFileobject.
SetobjFile=NewFile
objFile.Path=Path
AddittothePrivatecollection.
pcolFiles.AddobjFile,objFile.ShortName
Returnapointertothenewobject.
SetAdd=objFile
EndFunction
在本例中,到Collection的对象创建和添加发生在Add方法内部;而类则保留了完整的控制。任何必需的信息(例如文件的路径)是作为参数向方法提供的。由应用程序调用将文件添加到Collection的代码然后可以简化为:
Addafiletothecollection.
colFiles.Add”C:AUTOEXEC.BAT”
InadditiontotheAddmethod,theCollectionclassshouldalsoimplementtheItemandRemovemethods,aswellasaCountproperty:
PublicFunctionItem(KeyAsVariant)AsFile
Returnaniteminthecollection.
SetItem=pcolFiles.Item(Key)
EndFunction
PublicSubRemove(KeyAsVariant)
Removeanitemfromthecollection.
pcolFiles.RemoveKey
EndSub
PropertyGetCount()AsLong
Returnthenumberofitems.
Count=pcolFiles.Count
EndProperty
请注意,在这三种方法中,我们省略了错误处理–有些事情你是从来都不应该做的!至少应该包括一个错误处理器,通过使用Err对象的Raise方法来将错误传递、给调用过程。
图3这个表单通过显示文件信息来说明Collection类
Privatevariabletostorepath.
PrivatepstrPathAsString
PropertyGetPath()AsString
Returnstoredpathvalue.
Path=pstrPath
EndProperty
PropertyLetPath(strPathAsString)
DimstrFileAsString
Clearthecollection.
SetpcolFiles=NewCollection
Makesuretheresabackslash.
IfRight(strPath,1)<>””Then
strPath=strPath&””
EndIf
Getthefirstfile.
strFile=Dir(strPath&”*.*”,_
vbReadOnlyOrvbHiddenOrvbArchiveOrvbSystem)
DoUntilLen(strFile)=0
Addittothecollection.
CallAdd(strPath&strFile)
Getthenextfile.
strFile=Dir()
Loop
Savethepath.
pstrPath=strPath
EndProperty
图4向Collection类添加Path属性。将该属性和类设置为扫描目录并将所找到的每个文件添加到私有Collection对象。
扩展Collection类
现在,你可以通过声明Files类的一个实例来使用它了,并为曾经由Dir函数找到的每个文件反复调用该类的Add方法。但这不是我们的例子要完成的工作。为什么不是呢?使用Collection类的一个优点是你可以通过添加更多的属性和方法来扩展它的功能;不仅仅限于Add,Remove,Item,和Count。
在我们的Files类的情形中,它难道不对在类本身,而不是使用该类的每个应用程序里面,放置扫描目录的代码做更多的检测吗?这是面向对象设计的一个指导原则:将代码放在最靠近需要它的地方。
为了阐述这个概念,我们向Collection类添加了一个Path属性。当你设置这个属性的时候,这个类将对目录进行扫描,并向Collection对象添加它所找到的每个文件(见图4)。
当一个过程改变该类的Path属性的时候,将触发PropertyLet过程。在我们的例子中,它发生在你从浏览器对话框选择了一个路径之后。这里是完成用文件列表填充Collection任务的简单代码。
Reinitializethecollection.
SetmobjFiles=NewFiles
Setthepathproperty.
mobjFiles.Path=strPath
一旦设置了Path属性,Files类就将通俗化它自己的Collection,并且使它可以提供给应用程序。这已经是另一个例子了,在这个例子里面,过程的”guts”存在于类自己内部(你可以证明类已不再需要它的Add和Remove方法了。在有些应用程序中,可能确实是这样,但为了达到说明的目的,我们已经选择了留下它们作为该类的一部分)。
一些不利之处
使用VBACollection类的生活并不总是美酒和玫瑰。当你使用Collection类代替Collection对象时,必须放弃两样东西。第一样是Collection对象的默认方法,Item。默认的方法允许你从你的代码中省略单词”Item”。例如,如下两条语句是一样的,都是假定colFiles引用一个Collection对象。
Debug.PrintcolFiles.Item(1).Size
Debug.PrintcolFiles(1).Size
除非你正在使用的是VisualBasic5.0,否则没有办法为一个类指定默认的方法。因而,你必须总是显式调用Item方法。
Collection类的第二个主要的不足之处是不能创建列举函数。列举类就是可以使ForEach循环工作的类。如果你想重复Collection中的每一个项目,那么就必须用老式的方法来完成,也就是使用Count属性和ForNext循环。例如,下面的代码可以通俗化列表框:
Fillthelistboxwithinfo.
lstFiles.Clear
ForlngCount=1TomobjFiles.Count
WithmobjFiles.Item(lngCount)
lstFiles.AddItem.ShortName&_
Space(12-Len(.ShortName))&_
vbTab&.AttributeString&_
vbTab&.Size
EndWith
Next
请注意该过程是如何使用计数器变量lngCount来完成从1到Collection中项目数的循环的。With语句使用了Item方法来引用Collection中的每个对象。
请注意,VisualBasic5.0用户可以通过创建列举函数来克服这一局限。在VisualBasicBookOnline中搜索关键字”enumeration”可以得到更为详细的信息。->