Creating the CThings collection


Suppose you want to create a collection of things and that the things happen to be integers corresponding to the numbers 1 through 10. It might seem like overkill to create a collection to iterate through ten numbers, but it certainly makes for a simple example.


Figure 4-5 shows the Collection Wizard at work on a things collection. The Base Name field at the top of the form is where you enter the name of a single item. In this case, type in thing and click View Class. (When you click View Class, its caption changes to Clear All.) The wizard automatically picks some class names, variable names, and filenames for you and displays the result. If you don’t like its choices, change them and the wizard updates automatically. Since I designed the wizard, it’s no big surprise that I do like its choices. You have the source code if you get tired of overwriting defaults you don’t like.



Figure 4-5. The Collection Wizard.


You can also choose whether you want to make the collection public. For this throwaway sample, we don’t want a public collection. If you plan to put your collection in a component, you should make it public. There’s no need to make the iterator class public unless you plan to use it directly rather than providing it only for use with the For Each syntax. If you do specify a public iterator class, then public More, Skip, and Reset methods (that delegate to the IVariantWalker methods) will be created for you.


Finally, you can choose whether your collection will be able to hold objects, variables, or both. For example, the CDrives class is an object container and the CList class is a generic container. Our CThings class will handle only variables. A generic container is the most flexible choice, but if you specify an object or variable container, the wizard can code the Item method more efficiently.


You can see either of the proposed files by selecting the appropriate file from the View combo box, and you can write the files out to disk by clicking the Save Class Files button. The wizard specifically marks the spots where you must modify code. Search for the comment character followed by an exclamation point ('!) to find places where you must fill in the blanks. The dummy classes generated by the wizard actually compile and run if you put them in a project as is, although you’ll end up with an iterator object that walks through your empty collection.


The first thing you’ll do is define the collection data, initialize it, and share it with the iterator class. Normally, you would replace what the wizard gives you, but the following code leaves the wizard’s original comments for comparison.

‘ Private data structure
‘!Private data() As DataType
Private ai(1 To 10) As Integer

Private Sub Class_Initialize()
‘ Initialize private data
‘!data = initval
Dim i As Integer
For i = 1 To 10
ai(i) = i
Next
End Sub

‘ Friend properties to make data structure accessible to walker
‘!Friend Property Get Things(i As Long) ‘! As DataType
‘! Things = data(i)
‘!End Property
Friend Property Get Things(i As Long) As Integer
Things = ai(i)
End Property

These are obvious fill-in-the-blank changes. The wizard gives hints, but you define the data.


There’s no need to mess with the wizard’s implementation of NewEnum, but you have to do your own Count and Item members:

Public Property Get Count() As Integer
‘!Count = curcount
Count = 10
End Property

‘ Default property
‘!Public Property Get Item(vIndex As Variant) ‘! As DataType
Public Property Get Item(iIndex As Integer) As Integer
‘!Item = data(vIndex)
If iIndex >= 1 And iIndex <= 10 Then Item = ai(iIndex)
End Property

The wizard makes some general suggestions, but it doesn’t know whether to calculate your Count at run time or save it from an internal member (although you can bet it won’t often be hardcoded to a constant, as in this sample). The wizard knows even less about the Item property. It doesn’t know whether you want to support indexing by string, integer, or both. It can’t help with index validation or string lookup, but it can set the behind-the-scenes ID number that makes Item the default property. As for Add and Remove properties, the wizard doesn’t even try to guess whether you want them, much less how they should be coded.