Wiki Home

VFP Home Grown Collection

Namespace: WIN_COM_API
VFP versions prior to VFP 8 don't have a native Collection Class. This is a place to discuss different implementations of collection classes in VFP prior to VFP 8.

There are two types of home grown collections in VFP
Using a container class for a collection works well except that it can't support the kind of interface specified in the Collection topic. Using an array provides a much closer interface but isn't an object and doesn't have properties and methods.

Christof Wollenhaupt changed my mind on this by posting the following code on Compuserve: Pamela Thalacker

oData = NewObject("Collection")
oData.Items[3] = "three" ? oData.Items[3] ? oData.Items.Count Define Class Collection as Custom Dimension Items[3] Procedure Items_Access(tnIndex) If VarType(m.tnIndex) == "L" Local loInfo loInfo = NewObject("CollectionInfo") loInfo.Count = ALen(This.Items) Return loInfo Else Return This.Items[m.tnIndex] Endif EndProc Enddefine Define Class CollectionInfo as Custom Count = 0 Enddefine

Hmm, much exactly as I already posted here at the end of this article.... -- Vlad Grynchyshyn

More to the point, ADDOBJECT() inexorably conveys ownership and that's not something collections should intrinsically do. The base collection object should thus hold references, not values. Therefore forget containership unless there is a real ownership relationship between collection and collected. Thoughts?-- Steven Black

That make sense. The ownership relationship implies that when the parent is destroyed the owned objects are destroyed as well. Anything else?

What I'm trying to accomplish with these two topics is to determine the public interface(s) for collection classes ( Collection ) and the techniques for implementing these in VFP. -- ?jMM

Two other things I have seen done:
1. Items in the collection can be referenced as an array without using the Item method. For example, you could access the 3rd item in the collection as oCollection(3), instead of oCollection.Item(3).
This is not doable in VFP... in VB you can define a 'default' property and default 'Method.'

You can do this in VFP, but only using access/assign methods of the parent object when collection is really a property of that object. See sample in the files section at the Universal thread where I posted VFP collestion sample. General idea of it already described here at the end of this article. -- Vlad Grynchyshyn

2. Items can be accessed with non-numeric indices: if oCollection was a collection of form objects, then oCollection.Item("Invoice Form") or oCollection("Invoice Form") would return the form object in the collection with the caption "Invoice Form".
Codebook and Visual FoxExpress both have very good implementations of a collection that allow this. They have both a ReferenceCollection and a ChildCollection. The only thing you can't do in a VFP created collection is use For Each. Once again, VFE Solved this by creating an iterator for the collection class. It is a pretty robust collection class.

You can use For Each for my VFP collection. -- Vlad Grynchyshyn

-- Rick Hodder
After some investigation, I managed to make a collection-like property of object. Following is a simple sample of how to orginize collection-like access (Though he didn't highlight it, the neat feature here is improvized Default properties/methods!):
DEFINE CLASS coll AS custom
	Name = "coll"
	PROCEDURE a_access
		do case
			case vartype(m.nIndex1) == 'N'
				return THIS.a[m.nIndex1]
			case vartype(m.nIndex1) == 'C'
				return THIS.a[1]
			case vartype(m.nIndex1) == 'L'
				return THIS

	PROCEDURE a_assign
		LPARAMETERS vNewVal, m.nIndex1
		do case
			case vartype(m.nIndex1) == 'N'
				THIS.a[m.nIndex1] = m.vNewVal
			case vartype(m.nIndex1) == 'C'

				THIS.a[1] = m.vNewVal
			case ISNULL(m.nIndex1)
				THIS.a[1] = m.vNewVal

** Now, following are test commands:
oo = createobject("coll")
oo.a(1) = 5 && no error
? oo.a(1) && displays 5
? oo.a("qweqwe") && displays 5 anyway!
? oo.a.class && displays 'Coll'
? oo.a && displays 5
oo.a("qweqwe") = 1 && no error
? oo.a(1) && displays 1
oo.a.tag = '2'
? oo.a.tag && displays 2
&& Now, the main trick - allow to access objects in collection
oo.a(1) = createobject('coll')
? oo.a("qwe").class && displays 'Coll'
oo.a("qwe").a(1) = 5 && no error
? oo.a("qwe").a(1) && displays 5!

Using above approach, obviously, it is easy to make a collection property in VFP.

-- Vlad Grynchyshyn
Sample of use for each for above collection:
for each uitem in oo.a

See also Universal Thread files section where I posted full-functional VFP collection sample. -- Vlad Grynchyshyn.

There is also another collection object on the Universal Thread. It is simply titled "The best collection object in VFP". It was written by Rohullah Habibi and the download is just I have played with it a little, and it looks pretty good. -- Brian Mccord

Collections Library (ActiveX) for Visual FoxPro

The Collections ActiveX library includes Collection class with the interface similar to VFP's native Collection class.
LOCAL loItems as VfpCollections.VfpCollection
loItems = CREATEOBJECT('VfpCollections.VfpCollection')


* assuming a form is running

FOR EACH loItem IN loItems
	? loItem

? loItems.Contains('Mon')  && returns True
? loItems.Search('Mon')  && returns 2

nIndex = loItems.Search(_screen.Forms[1])
? loItems.Item(nIndex).Caption

The Stack and the Queue classes are also included.
-- Anatoliy Mogylevets

See also collection class, VFP home grown collection, COM collection, VFP collection, collection, objects collection

Category Class Design
( Topic last updated: 2013.10.08 09:45:42 AM )