Re: Collection as sub-set of collection
- From: "Mike D Sutton" <EDais@xxxxxxxx>
- Date: Thu, 16 Mar 2006 17:45:59 -0000
This is about VB6, hope this is the right forum!
Yup
Say I have two collections: Cars and Manufacturers e.g.,
Cars = Focus, Escort, Puma, Cougar, 626, 323, Clio, Espace, 106, 206,
307
Manufacturers = Ford, Mazda, Renault, Peugeot
I have a couple of questions about inter-referencing between them:
1) Can each 'Car' reference the appropriate 'Manufacturer' object, such
that Cars("Focus").Manufacturer returns (a reference to) the same
object as Manufacturers("Ford")?
Yes, when you set an object variable in VB you set a reference to the object.
2) Can each 'Manufacturer' contain a 'MyCars' collection which is
essentially a subset of the 'Cars' collection, BUT REFERENCES THE SAME
OBJECTS. That is, say, if I do
Manufacturers("Ford") .MyCars("Focus").Age = 6
then
n = Cars("Focus").Age
n = 6
If this can be done, how?
If it can only be simulated, what is the best method?
The Manufacturer object would need to expose a collection property with the appropriate car objects referenced within
it. Be careful though with this since you're getting into something called circular references (Manufacturer references
Car which references Manufacturer which references Car.. etc..)
You must explicitly break this link for your object tree to terminate properly. Another option is to use a 'soft
pointer' from the car back to the manufacturer, but that's a somewhat advanced technique that can quickly get you into a
lot of problems, so it's probably best to sick away from that route for now.
Here's a quick example of how to set up the object hierarchy:
'*** clsCar.cls
Private m_Name As String
Private m_Age As Long
Private m_Manufacturer As clsManufacturer
Public Property Get Name() As String
Name = m_Name
End Property
Public Property Let Name(ByRef inNew As String)
m_Name = inNew
End Property
Public Property Get Age() As Long
Age = m_Age
End Property
Public Property Let Age(ByVal inNew As Long)
m_Age = inNew
End Property
Public Property Get Manufacturer() As clsManufacturer
Set Manufacturer = m_Manufacturer
End Property
Public Property Set Manufacturer(ByVal inNew As clsManufacturer)
Set m_Manufacturer = inNew
End Property
'***
'*** clsManufacturer.cls
Private m_Name As String
Private m_Cars As Collection
Public Property Get Name() As String
Name = m_Name
End Property
Public Property Let Name(ByRef inNew As String)
m_Name = inNew
End Property
Public Property Get Cars() As Collection
Set Cars = m_Cars
End Property
Private Sub Class_Initialize()
' Object manages its own internal cars collection
Set m_Cars = New Collection
End Sub
Private Sub Class_Terminate()
Set m_Cars = Nothing
End Sub
'***
'*** Main.bas
Private Sub Main()
Dim Manufacturers As Collection
Dim FordFocus As clsCar
' Create a new collection of manufacturers
Set Manufacturers = New Collection
' Create a new manufacturer and car
Call Manufacturers.Add(NewManufacturer("Ford"), "Ford")
Set FordFocus = NewCar("Focus", 5, Manufacturers("Ford"))
' Add the car to the manufacturer
Call Manufacturers("Ford").Cars.Add(FordFocus, "Focus")
' Display the initial age
Debug.Print Manufacturers("Ford").Cars("Focus").Age
' Set the new age on the original object
FordFocus.Age = 6
' Show how the referenced object has also been changed
Debug.Print Manufacturers("Ford").Cars("Focus").Age
' Break circular references
Call TerminateObjects(Manufacturers)
' Done with collection
Set Manufacturers = Nothing
End Sub
Private Function NewCar(ByRef inName As String, ByVal inAge As Long, _
ByVal inManufacturer As clsManufacturer) As clsCar
Set NewCar = New clsCar ' Car constructor
NewCar.Name = inName
NewCar.Age = inAge
Set NewCar.Manufacturer = inManufacturer
End Function
Private Function NewManufacturer(ByRef inName As String) As clsManufacturer
Set NewManufacturer = New clsManufacturer ' Manufacturer constructor
NewManufacturer.Name = inName
End Function
Private Sub TerminateObjects(ByVal inManufacturers As Collection)
Dim Manufacturer As clsManufacturer
Dim Car As clsCar
' Break circular references
If (Not (inManufacturers Is Nothing)) Then
' Iterate all manufacturers
For Each Manufacturer In inManufacturers
' Iterate all cars
For Each Car In Manufacturer.Cars
' Break link back to parent
Set Car.Manufacturer = Nothing
Next Car
Next Manufacturer
End If
End Sub
'***
Unfortunately using the default collection type means there can be anything in the collection, which would cause huge
problems with the above code. To circumvent this you can write your own collection object which wrap a standard VB
collection object, but restrict what can be added to it (I.e. only clsCar object could be added to your clsCarCollection
collection object.)
The other huge benefit of this is that you get intellisense on the .Item() method of the collection so you can see all
of the available methods/properties of the objects inside the collection. Here's an old post with an example of using
wrapped collections in a similar kind of problem:
http://groups.google.co.uk/group/microsoft.public.vb.general.discussion/msg/a8da881d902621db
Also, if you want For ... Each functionality on your wrapped collections, then have a look at this old post:
http://groups.google.co.uk/group/microsoft.public.vb.general.discussion/tree/browse_frm/thread/28a3dcedaf342674
Hope this helps,
Mike
- Microsoft Visual Basic MVP -
E-Mail: EDais@xxxxxxxx
WWW: Http://EDais.mvps.org/
.
- Follow-Ups:
- Re: Collection as sub-set of collection
- From: Kyudos
- Re: Collection as sub-set of collection
- References:
- Collection as sub-set of collection
- From: Kyudos
- Collection as sub-set of collection
- Prev by Date: Using Multiple form in VB.NET
- Next by Date: Re: Using Multiple form in VB.NET
- Previous by thread: Collection as sub-set of collection
- Next by thread: Re: Collection as sub-set of collection
- Index(es):
Relevant Pages
|