There are two different ways of creating a keyed collection, one with collection style Factory and one with collection style Collection.
By default the Style property of a keyed collection is Factory. This means that a new item in the collection is created whenever the collection is accessed using a value in the key field that does not already exist in the collection.
Alternatively the Style can be Collection. This means that the application must explicitly create the items in the collection by using a SET_REF command.
The advantage of using references is that you can have direct control over memory usage by explicitly creating and destroying components. The larger and more complex your application is, the more important it becomes to ensure that your application uses memory effectively.
Factory Collections
For any given object called #Object defined in a collection like this (where the default Style() is shown):
Define_Com Class(#Prim_KCol<#Object #Key>) Name(#Collection) Style(Factory)
any reference to an item in the collection, for example:
Set #Collection<#Key> ................
will automatically create an instance of #Object if an object with key #Key is not already in the collection.
Collection Style Collections
If the collection is defined like this:
Define_Com Class(#Prim_KCol<#Object #Key>) Name(#Collection) Style(Collection)
then
Set #Collection<#Key> ................
will fail with an error message if an object with key #Key is not already in the collection. To handle a Style(Collection) collection correctly in this situation you need to code this:
If_Ref #Collection<#Key> is(*null)
Set_Ref #Collection<#Key> To(*Create_as #Object)
Endif
Set #Collection<#Key> ................
This code first checks whether #Collection<#Key> exists in the collection. If it does not then a Set_Ref command is used to create a new instance of #Object and then assign the reference to the new object into the collection.
This may seem like more code, but in fact Style(Collection) collections are very useful because you can check whether something exists in the collection and then control when and how it is added.
Note that only keyed collections support the Style(Factory) and Style(Collection) properties. All other collection types (eg: array, list, sorted array, etc) are implicitly Style(Collection) collections.
Factory and Collection Style Example
This example shows you the difference between coding factory and collection style collections.
The factory buttons are automatically created when the properties of the buttons are set:
Set Com(#Button_Factory<#Use_Key>) Parent(#Com_Owner) Height(20) Width(100) Left(2) Top(#Next_Top) Caption('Factory Button')
The collection buttons are explicitly created using a SET_REF command after which the properties of the buttons are set:
Set_Ref Com(#Button_Collection<#Use_Key>) To(*create_as #Prim_Phbn)
Set Com(#Button_Collection<#Use_Key>) Parent(#Com_Owner) Height(20) Width(100) Left(2) Top(#Next_Top) Caption('Collection Button')
In both styles of collection the buttons are made visible by using the Realize method:
Invoke Method(#Button_Collection<>.Realize)
Source for the Factory/Collection Example
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Clientheight(383) Clientwidth(182) Height(410) Left(452) Top(63) Visualstyle(#VS_NORM) Width(190)
* Style(Factory) and Style(Collection) collections
* Define a Style(Factory) keyed collection of buttons
Define_Com Class(#Prim_kCol<#Prim_PHBN #Std_Num>) Name(#Button_Factory)
* Define a Style(Collection) keyed collection of buttons
Define_Com Class(#Prim_kCol<#Prim_PHBN #Std_Num>) Name(#Button_Collection) Style(Collection)
* Form layout is 2 buttons to initiate the creation of collection of buttons
Define_Com Class(#PRIM_PHBN) Name(#PHBN_FACTORY) Caption('Make 3 Factory Buttons') Displayposition(2) Left(16) Parent(#COM_OWNER) Tabposition(1) Top(8) Width(137)
Define_Com Class(#PRIM_PHBN) Name(#PHBN_COLLECTION) Caption('Make 3 Collection Buttons') Displayposition(1) Left(16) Parent(#COM_OWNER) Tabposition(2) Top(40) Width(137)
* Incrmental value used to position buttons
Define Field(#NEXT_TOP) Reffld(#STD_NUM) Default(80)
Define Field(#USE_KEY) Reffld(#STD_NUM)
* ----------------------------------------------------------------------
* #PHBN_FACTORY : Create 3 more buttons in the Style(Factory) collection
* ----------------------------------------------------------------------
Evtroutine Handling(#PHBN_FACTORY.Click)
Begin_Loop To(3)
* Get the next key to be used
Change Field(#USE_KEY) To('#Button_Factory.ItemCount + 1')
* Create the button simply by referencing it. Since the item does
* not exist in the collection and the collection is Style(Factory)
* then a new button will be automatically ""manufactured" .....
Set Com(#Button_Factory<#Use_Key>) Parent(#Com_Owner) Height(20) Width(100) Left(2) Top(#Next_Top) Caption('Factory Button')
* Increment the next top position
Change Field(#NEXT_TOP) To('#Next_Top + 26')
End_Loop
* Now that the buttons have been created make them visible by realizing them
Invoke Method(#Button_Factory<>.Realize)
Endroutine
* ----------------------------------------------------------------------------
* #PHBN_COLLECTION : Create 3 more buttons in the Style(Collection) collection
* -----------------------------------------------------------------------------
Evtroutine Handling(#PHBN_COLLECTION.Click)
Begin_Loop To(3)
Change Field(#USE_KEY) To('#Button_Collection.ItemCount + 1')
Set_Ref Com(#Button_Collection<#Use_Key>) To(*create_as #Prim_Phbn)
Set Com(#Button_Collection<#Use_Key>) Parent(#Com_Owner) Height(20) Width(100) Left(2) Top(#Next_Top) Caption('Collection Button')
Change Field(#NEXT_TOP) To('#Next_Top + 26')
End_Loop
* Now that the buttons have been created make them visible by realizing them
Invoke Method(#Button_Collection<>.Realize)
Endroutine
End_Com