You can use collections to group a set of related items, usually objects, which can be of any type. Collections provide a mechanism for working with objects stored in containers and include standard ways for accessing and iterating through objects in a collection. The Collection class functions as a true container class, even though it does not include the AddObject method like the Form and PageFrame classes.
The Collection class is a base class that you can subclass in program (.prg) or visual class library (.vcx) files.
The position of an item in a collection can vary and change when changes occur in the collection.
Collections support the enumerations of items performed with the FOREACH command based on the position of items. You can control the position of these items by using the eBeforeItem or eAfterItem parameters associated with the Add method for collection objects. You can use an index value of 1, or one-based enumeration, to refer to the first item in a collection, or you can use a key value by setting the KeySort property. Collections are one-based for consistency and compatibility with other internal Visual FoxPro collections.
Make sure that either all the items in a collection have keys or none of them have keys. Deciding whether all items have keys or do not have keys provides more efficient item searching when using the Item method for collection objects and the FOR EACH command.
You can use a collection in a Visual FoxPro Component Object Model (COM) server that other COM Servers can access.
You can hide the Add and Remove methods for collection objects from public use by subclassing the collection object and marking the subclassed members as Hidden or Protected. If you do so, you need to add the collection members in the Init event or via some other method.
Items that are added to collections have the same scope as any other memory variable.
Because Collection objects support default methods, for example, Item (Collection Class), you need to be aware of the search order for these methods. A Collection object method takes precedence over a standard user-defined function (UDF) call. The following list shows the order in which Visual FoxPro searches for a function name:
Visual FoxPro native function
Collection object default method
UDF defined in the local program (.prg) file
UDF defined in calling program (.prg) files
Named program in the application (.app or .exe) file
Named program along the SET PATH list
When Visual FoxPro releases a collection, which contains object references, it also releases any objects in the collection if they are not referenced elsewhere. Make sure to release objects and any references to those objects from a collection before releasing the collection itself from memory.
Visual FoxPro does not support intrinsic type safety. Therefore, to enforce type safety with collections, you must provide it for the class.
A native Visual FoxPro collection is designed such that the Item method makes it possible for you to run user-defined code. The Visual FoxPro Debugger does not support the evaluation of object members that are implemented as method calls. Therefore, you cannot evaluate the items in a collection.
To help debug a collection, you might write code such as the following examples, which add a member array named "Items" to reference each of the collection items:
LOCAL oCol AS Collection oCol=CREATEOBJECT("collection") oCol.Add(123) oCol.Add("AAA") oCol.Add(CREATEOBJECT("custom")) oCol.Add(CREATEOBJECT("session")) oCol.Add(CREATEOBJECT("collection")) oCol.Item(5).Add(456) oCol.Item(5).Add("BBB") oCol.Item(5).Add(CREATEOBJECT("session")) oCol.Item(5).Add(CREATEOBJECT("collection")) oCol.Item(5).Item(4).Add(789) oCol.Item(5).Item(4).Add("CCC") oCol.Item(5).Item(4).Add(CREATEOBJECT("session")) oCol.Item(5).Item(4).Add(CREATEOBJECT("Collection")) DebugCollection(oCol) DEBUG SUSPEND PROCEDURE DebugCollection(oCollection) IF oCollection.Count=0 RETURN ENDIF oCollection.AddProperty("Items") DIMENSION oCollection.Items[oCollection.Count] FOR i = 1 TO oCollection.Count oCollection.Items[m.i]=oCollection.Item[m.i] IF VARTYPE(oCollection.Item[m.i])="O" AND ; oCollection.Item[m.i].BaseClass="Collection" IF oCollection=oCollection.Item[m.i] LOOP ENDIF DebugCollection(oCollection.Item[m.i]) ENDIF ENDFOR ENDPROC
At run time, the following example creates forms and a collection, adds forms to the collection using the Collection class Add method, displays the name of each form in the collection, and displays the number of forms in the collection:
loForm1 = CREATEOBJECT("Form") loForm2 = CREATEOBJECT("Form") loCol = CREATEOBJECT("Collection") loCol.Add(loForm1) loCol.Add(loForm2) FOR EACH loObj IN loCol ? loObj.Name ENDFOR ? loCol.Count
The following example defines a Form class which adds text boxes, buttons objects, and a collection to the form. When added to the form at run time, the collection class adds all the objects on the form to itself. The example then iterates through the collection to adjust the position of the control and prints its name to the screen.
LOCAL loForm, loItem, lnTop loForm = CREATEOBJECT("myForm") lnTop=0 FOR EACH loItem IN loForm.myCollection TRY loItem.Top = lnTop lnTop=lnTop+20 ? loItem.Name CATCH ENDTRY ENDFOR loForm.Show(1) DEFINE CLASS myForm AS Form AllowOutput=.F. AutoCenter=.T. ADD OBJECT myTextBox1 AS TextBox ADD OBJECT myTextBox2 AS TextBox ADD OBJECT myButton1 AS CommandButton ADD OBJECT myButton2 AS CommandButton ADD OBJECT myCollection AS col1 ENDDEFINE DEFINE CLASS col1 AS Collection PROCEDURE Init FOR i = 1 TO THISFORM.Objects.Count THIS.Add(THISFORM.Objects(m.i)) ENDFOR ENDPROC ENDDEFINE