Using a Collection Object in a Custom Class

Fuse3k

Registered User.
Local time
Today, 01:48
Joined
Oct 24, 2007
Messages
74
Hello!

I'm writing a custom class in Access and I have a Collection object declared as as Public, Read/Write property. The Collection will hold objects related to the main class object. I want to be able to add objects to the Collection from within the class, but I don't want to user to add/edit/remove from outside of the class. I.E. the collection class is Read Only externally and read/write internally.

It's important that the user has the ability to iterate through the collection using For Each...Next, so I don't want to lose that functionality.

How would one go about doing this?

Thank you!
 
Please tell us more about
the main class object
.

Can you show readers the code and sample usage?
 
Say your custom class is clsThing

Define your collection and create an instance
Code:
dim colMyCollection as collection
set colMyCollection as new collection
Then use the add method of the collection

Code:
colMyCollection.Add clsThing1
colMyCollection.add clsThing2

Then you can loop through your collection
Code:
For each clsThing in collMyCollection
  (do whatever)
next

The first item in the collection is collMyCollections(1) is clsThing1

You could give each instance of clsThing its own unique identifier so you can find a particular instance of clsThing if you are adding/removing objects from your collection.

For anyone wondering why use a collection of custom classes (on indeed a collection of forms), I had a situation some years ago with a training organisation, and while the initial set up had some complexity, it made it a breeze to do things like up open up multiple instances of the same form to show training classes being conducted.
 
The key to controlling the external access is to any variables is to declare them Private.

Then build the Properties and Methods to control the read and write. A Property Get will enable external reading while a Property Set or Property Let will allow writing. How you set up these properties governs who can access and under what circumstances.

I you want them you must recreate the Properties of Private objects such as you collection at the class level. You can simply pass the instructions through to the internal object but often the developer can put in a lot more functionality at this level than the embedded object.

With a Collection you can add index functionality such as testing if an Item by a particular name is already held in the Collection. However in this case I prefer to use a Dictionary from the Scripting Library because this object already has that functionality.

The limit to how you can interact with your properly set up class object is mostly down to your imagination.

For example I have used them storing database Connections. Inside my class object I simply ask for a connection and it manages checking for it already existing then all the actions required to return it to me. However none of this is exposed to the application.

In the case of the recordsets Dictionary, the methods are exposed using Properties and Methods of the Class object. My application simply initialises an instance as it starts.

Then all the app has to do is ask for one and the class object checks for it already being in the Dictionary and returns it if available. Otherwise it would look up its location through two different indexes, retrieve the text file, store critical information about it for future use, parse it into a recordset which is then stored in the Dictionary. Then return it to the GetRecordset Method.

It is really comes down to how you want your application to interact with the object. The key to good really usable class design is that interface. Whatever you do don't include any global variables inside the class. Pass everything inside Methods and Properties.

The concept of an Interface is actualised in more advanced Object Oriented programming and is very important.
 
I don't think you need the exposed property to be read/write, but check out this pattern . . .
Code:
Private m_items As VBA.Collection

Property Get Items() As VBA.Collection
[COLOR="Green"]'  the object is not created until called - known as a lazy load[/COLOR]
   If m_items Is Nothing Then Set m_items = BuildCollection
   Set Items = m_items
End Property

Private Function BuildCollection() As VBA.Collection
[COLOR="Green"]   'returns a custom collection built for this class[/COLOR]
End Function
See how the collection gets built inside the class, and only once. Also, the collection is not built if it is not called. This way your classes can expose lots of very rich objects, and still be fast, because they will only create those complex objects if consumers actually call them.
 
I don't think you need the exposed property to be read/write,

Absolutely essential if the variables are Private.

Remember the original question was about controlling the read and write external to the class. The only way to do this is to make the variables Private and use properties or methods to access them and manage the changes.
 
I think for the beginner it is easy to become confused between whether the object itself is read/write, or whether its members are. With a custom cClass that exposes a read-only collection as follows . . .
Code:
private m_col as new vba.collection

property Get MyCollection as vba.collection
   set MyCollection = m_col
end property
. . . this code will fail . . .
Code:
dim tmp as new cClass
set tmp.MyCollection = new vba.collection
. . . because MyCollection is a read-only property, and we can't write a new collection object to the property. But this code is fine . . .
Code:
dim tmp as new cClass
tmp.MyCollection.Add Forms!SomeOpenForm
. . . where we add a member to the collection, using methods of the collection. The distinction I want to draw is that even though the property that exposes the Collection is read-only, the collection itself is still fully open for business and all of its members are accessible. Like, I don't need my cClass object to expose an Add or a Remove method, or a Count property. These are still exposed and fully accessible members of the exposed collection.
 
The distinction I want to draw is that even though the property that exposes the Collection is read-only, the collection itself is still fully open for business and all of its members are accessible. Like, I don't need my cClass object to expose an Add or a Remove method, or a Count property. These are still exposed and fully accessible members of the exposed collection.

That is a good point but simply exposing a Private Collection like that would largely defeat the purpose of having a Private Collection.

Instead one would use a Method that controlled the interaction in terms of the functionality of the Class from a user's perspective. They need never even know anything about Collections or Dictionaries.

In my earlier example above I don't directly expose the Recordsets Collection of the Class in any way. Instead I have SetRecordset() and GetRecordset() Methods. The class user does not need to know anything about how those recordsets are stored or retrieved.

Referencing and interacting directly with the embedded class though its primitive methods largely misses one of the main advantages of using a class in the first place.
 
Thank you all for your contribution to the thread! I ended up creating a custom class which is a "wrapper class" of the Collection object. I wrapped all but the Add method so it's essentially read-only externally and internally, I can simply refer to the private collection variable to invoke the Add method. Works perfectly!!

Thanks again!
 
I wrapped all but the Add method so it's essentially read-only externally and internally, I can simply refer to the private collection variable to invoke the Add method.

It isn't a private collection if it is exposed. Regardless of what methods you wrapped, if the collection object is exposed for Add it is exposed for its other methods too.
 
to be fair, I expect it won't matter so much if you use it in the way you intend to.

with a real class you would be able to declare manipulate multiple "yourcollectionclass" objects simultaneously. I suspect you might only be able to have a single instance, although I may be wrong.
 
Yeah, you can create multiple instances of VBA classes.
 

Users who are viewing this thread

Back
Top Bottom