By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,016 Members | 1,024 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,016 IT Pros & Developers. It's quick & easy.

Why can't I copy a collection class from one instance to another?

P: n/a
Either I don't understand (entirely possible), or there's no way to
copy parts of a class hierarchy from one instance to another.

Say I have a class called Foo, and it contains, among other things, a
custom collection called SubFoos. If I do something like

Dim MyFoo1 As Foo
Dim MyFoo2 As Foo

'call something to populate MyFoo1 and its SubFoos...

Debug.Print MyFoo1.SubFoos.Count

'pretend it's, say, 18. What a lot of SubFoos!

Set MyFoo2 = MyFoo1

Set MyFoo1 = Nothing

Debug.Print MyFoo2.SubFoos.Count

The last line will always give me 0. The only way, it seems, to copy
the members of the SubFoos collection from MyFoo1 to MyFoo2 is to
iterate through it, and add each one. And yet all the Foo-level stuff
is there.

I think this has something to do with pointers and other such "real"
"programming" notions that I have never learned, but still, frankly, it
blows. What's the point of building all that sexy self-enforcing
structure only to have to turn around and walk it like a plain old
recordset or whatever when you want a simple copy? Is this an
Access/VBA problem, or is it common to all programming languages? Or
am I just too green to get it?

Apr 14 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a

You don't give the implementation details or your collection class but I'm
guessing your doing something like exposing the collection as a public
member of the class. If so this is wrong, the collection should be private
to the class and you then provide methods of the class to manipulate the
collection.

The following is a very simple example of a collection class implementation
(I've omitted the Item and Remove methods for clarity).
Foo Class
=========
Option Explicit

Private SubFoos As Collection

Sub Add(RHS As Object)
If SubFoos Is Nothing Then
Set SubFoos = New Collection
End If
SubFoos.Add RHS
End Sub

Function Count() As Long
Count = SubFoos.Count
End Function

=========

Test Code
=========
Function TestFoo()
Dim MyFoo1 As Foo
Dim MyFoo2 As Foo
Dim MyObj As Object
Dim intX As Integer

Set MyFoo1 = New Foo

For intX = 1 To 10
MyFoo1.Add MyObj
Next
Debug.Print MyFoo1.Count

Set MyFoo2 = MyFoo1
Debug.Print MyFoo1.Count, MyFoo2.Count

Set MyFoo1 = Nothing
Debug.Print MyFoo2.Count
Set MyFoo2 = Nothing

End Function

=========

Results
=========
10
10 10
10

=========
--

Terry Kreft
"downwitch" <do*******@gmail.com> wrote in message
news:11**********************@z34g2000cwc.googlegr oups.com...
Either I don't understand (entirely possible), or there's no way to
copy parts of a class hierarchy from one instance to another.

Say I have a class called Foo, and it contains, among other things, a
custom collection called SubFoos. If I do something like

Dim MyFoo1 As Foo
Dim MyFoo2 As Foo

'call something to populate MyFoo1 and its SubFoos...

Debug.Print MyFoo1.SubFoos.Count

'pretend it's, say, 18. What a lot of SubFoos!

Set MyFoo2 = MyFoo1

Set MyFoo1 = Nothing

Debug.Print MyFoo2.SubFoos.Count

The last line will always give me 0. The only way, it seems, to copy
the members of the SubFoos collection from MyFoo1 to MyFoo2 is to
iterate through it, and add each one. And yet all the Foo-level stuff
is there.

I think this has something to do with pointers and other such "real"
"programming" notions that I have never learned, but still, frankly, it
blows. What's the point of building all that sexy self-enforcing
structure only to have to turn around and walk it like a plain old
recordset or whatever when you want a simple copy? Is this an
Access/VBA problem, or is it common to all programming languages? Or
am I just too green to get it?

Apr 14 '06 #2

P: n/a
"downwitch" <do*******@gmail.com> wrote in message
news:11**********************@z34g2000cwc.googlegr oups.com...
Either I don't understand (entirely possible), or there's no way to
copy parts of a class hierarchy from one instance to another.

Set MyFoo2 = MyFoo1


Unfortunately, there is no object clone method in access...

You can prevent the object from going out of scope like

So, in the above...you just are pointing MyFoo2 to MyFoo1...

However!!..if you create a new instance of the object FIRST and then set it
to the previous ..you get a copy of the pointer..but NOT the data!!

So, change the above to

set MyFoo2 = new Foo

set MyFoo2 = MyFoo1
set MyFoo1 = nothing....

At this point, you CAN now still use MyFoo2. However, this will NOT SOLVE
your problem. They are still both the SAME object...if you change one..the
other changes. (but, now we only got one since the use of the =
nothing...but they are NOT independent).

Unfortunately, this means you have to write your own clone method of the
class....

you can use

public function myClone as Foo

dim f as new foo

f.m_BollingPoint = me.m_BollingPoint
......et.c etc. etc...

You have to write one line of code to for everything and peiice of data your
have....

set MyClone = f

end function.

Then, you can go

dim antoherFoo as new foo

set anotherFoo = myFoo1.MyClone

--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal
Apr 14 '06 #3

P: n/a
In place of the = nothing...try changing the value of one of the
objects....you will see that the other changes....

eg:

Set MyFoo2 = MyFoo1
Debug.Print MyFoo1.Count, MyFoo2.Count

MyFoo1.Add MyObj <--- add this

Set MyFoo1 = Nothing

Debug.Print MyFoo2.Count
Set MyFoo2 = Nothing

you will get a value of 11 for the above last print....despite the first
object being set = nothing...

When you set MyFoo1 = nothing...you are killing the pointer...but they both
are still the same copy.....

Try adding one value to the first one BEFORE you do a set MyFoo1 =
nothing...and you will STILL find the 2nd instance will have that new
value...

You have to write code to copy the class......

--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal
Apr 14 '06 #4

P: n/a
rkc
downwitch wrote:
Either I don't understand (entirely possible), or there's no way to
copy parts of a class hierarchy from one instance to another.


You should really post actual code that you have tried
for something like this. I don't see the behaviour you
describe so it's must be your implementation.

<clsStuff>
Option Compare Database
Option Explicit

Private stuff As VBA.Collection
Private index As Long

Public Function NextStuff() As Variant
index = index + 1
If index <= stuff.count Then
NextStuff = stuff(index)
End If
End Function

Public Function HasMoreStuff() As Boolean
HasMoreStuff = index < stuff.count
End Function

Public Sub ResetStuff()
index = 0
End Sub

Public Sub AddStuff(v As Variant)
stuff.Add v
End Sub

Private Sub Class_Initialize()
Set stuff = New VBA.Collection
End Sub

Private Sub Class_Terminate()
Set stuff = Nothing
End Sub
</clsStuff>

<Test Form>
Option Compare Database
Option Explicit

Dim stf2 As clsStuff

Sub TestStuff()
Dim stf As clsStuff

Set stf = New clsStuff
Set stf2 = New clsStuff

With stf
.AddStuff "Thing One"
.AddStuff "Thing Two"
.AddStuff "Thing Three"
While .HasMoreStuff
Debug.Print .NextStuff
Wend
Set stf2 = stf
Set stf = Nothing
End With

Set stf = Nothing

End Sub

Sub ShowStuff2(stf As clsStuff)
stf.ResetStuff
While stf.HasMoreStuff
Debug.Print "2: "; stf.NextStuff
Wend
End Sub

Private Sub Command0_Click()
Call TestStuff
End Sub

Private Sub Command1_Click()
Call ShowStuff2(stf2)
End Sub

</Test Form>
Apr 14 '06 #5

P: n/a
This is the point. The other posts don't show the key thing here,
which is that even though you can set an Instance2 to _point to_ an
Instance1, it's not because you say "make Instance1 nothing" that it
truly goes away. In other words, it's not a clone, it's two pointers
to the same single object.

I would've posted real code, but (1) my class hierarchies are
hydra-like, huge, and impossible, and (2) I am more interested in the
theoretical wrongheadedness of why Access/VBA doesn't do this properly,
and (less importantly) if this is common to classes in other
programming environments. Besides, Albert nailed it with his simple
addition to Terry's code: change one, you change the other, meaning
there's one, not two. Still a slightly different question from why
public instances of the same class collection can't be set to equal
each other, but the two phenomena must be linked; if you could make a
proper clone of an instance, then you could reasonably expect to make a
proper clone of a part of an instance.

Is this different from working with, say, two string variables, or is
it all just pointers? At what point does something really get
"created"?
Albert D. Kallal wrote:
In place of the = nothing...try changing the value of one of the
objects....you will see that the other changes....

eg:

Set MyFoo2 = MyFoo1
Debug.Print MyFoo1.Count, MyFoo2.Count

MyFoo1.Add MyObj <--- add this

Set MyFoo1 = Nothing

Debug.Print MyFoo2.Count
Set MyFoo2 = Nothing

you will get a value of 11 for the above last print....despite the first
object being set = nothing...

When you set MyFoo1 = nothing...you are killing the pointer...but they both
are still the same copy.....

Try adding one value to the first one BEFORE you do a set MyFoo1 =
nothing...and you will STILL find the 2nd instance will have that new
value...

You have to write code to copy the class......

--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal


Apr 15 '06 #6

P: n/a
rkc
downwitch wrote:
This is the point. The other posts don't show the key thing here,
which is that even though you can set an Instance2 to _point to_ an
Instance1, it's not because you say "make Instance1 nothing" that it
truly goes away. In other words, it's not a clone, it's two pointers
to the same single object.

I would've posted real code, but (1) my class hierarchies are
hydra-like, huge, and impossible, and (2) I am more interested in the
theoretical wrongheadedness of why Access/VBA doesn't do this properly,
and (less importantly) if this is common to classes in other
programming environments. Besides, Albert nailed it with his simple
addition to Terry's code: change one, you change the other, meaning
there's one, not two. Still a slightly different question from why
public instances of the same class collection can't be set to equal
each other, but the two phenomena must be linked; if you could make a
proper clone of an instance, then you could reasonably expect to make a
proper clone of a part of an instance.

Is this different from working with, say, two string variables, or is
it all just pointers? At what point does something really get
"created"?


I did completely miss your actual question.
In Visual Basic/VBA there is no built into the language way
of creating an independent clone of an object. You have to
do what you don't think you should have to do. That is to copy
the actual base data piece by piece.

You can ponder it till the end of time, but that's the way it is.

Apr 15 '06 #7

P: n/a
>if this is common to classes in other
programming environments.

Yes, it is common to true object programming environments. You often have to
still write a clone method, but the properties and methods of the object
*usually* can be un-corked out to a serialized string that can be saved (in
fact, we call this serialization). It is this "string" of data that can
then be loaded back into the object.

This gives two benefits.

you can actually "save" the state of the object to your hard disk..and
next time you run the program...re-load the object. Thus, you can actually
use objects, and save them to a database, or even a file on hard disk.

The side benefit of this serialization process is that the code to clone
a object his thus very easy to write....

And, even more important, with web based services...you can *transfer* a
object across the connection this way.

So, if the language at hand does not support clone of the object (not all
do), but does support what we call serialization, then cloning is easy
anyway...

We have neither clone, nor serialization available in VB, or ms-access,
which by the way is the same as VB6...

You do have serialization in vb.net however.....
--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal
Apr 18 '06 #8

P: n/a
OK, I thought it was fairly obvious what was on from my example.

A class variable contains a pointer to a piece of memory, initially this is
null but when you instantiate it using the New keyword (or CreateObject)
then a piece of memory is set aside for the class an the variable is set to
point to this piece of memory.

If you have a second variable which you set equal to an existing class
variable then you are copying the value of that variable, that is you are
copying the pointer to the memory which holds the class information. So you
aren't creating a copy of the class you are creating a copy of the pointer
to the class.

In order to create a copy of the class you would need to do one of two
things.
a)
instantiate a new class object
copy all the property values from the original to the new class
object

This isn't so difficult if you implement a properties collection on the
class

You could in theory
b)
instantiate a new class object
determine the length of memory containing the class data of the
original
copy the memory block of the original class data over the new class
data

This would involve a fair amount of API work.

--

Terry Kreft
"downwitch" <do*******@gmail.com> wrote in message
news:11**********************@i40g2000cwc.googlegr oups.com...
This is the point. The other posts don't show the key thing here,
which is that even though you can set an Instance2 to _point to_ an
Instance1, it's not because you say "make Instance1 nothing" that it
truly goes away. In other words, it's not a clone, it's two pointers
to the same single object.

I would've posted real code, but (1) my class hierarchies are
hydra-like, huge, and impossible, and (2) I am more interested in the
theoretical wrongheadedness of why Access/VBA doesn't do this properly,
and (less importantly) if this is common to classes in other
programming environments. Besides, Albert nailed it with his simple
addition to Terry's code: change one, you change the other, meaning
there's one, not two. Still a slightly different question from why
public instances of the same class collection can't be set to equal
each other, but the two phenomena must be linked; if you could make a
proper clone of an instance, then you could reasonably expect to make a
proper clone of a part of an instance.

Is this different from working with, say, two string variables, or is
it all just pointers? At what point does something really get
"created"?
Albert D. Kallal wrote:
In place of the = nothing...try changing the value of one of the
objects....you will see that the other changes....

eg:

Set MyFoo2 = MyFoo1
Debug.Print MyFoo1.Count, MyFoo2.Count

MyFoo1.Add MyObj <--- add this

Set MyFoo1 = Nothing

Debug.Print MyFoo2.Count
Set MyFoo2 = Nothing

you will get a value of 11 for the above last print....despite the first
object being set = nothing...

When you set MyFoo1 = nothing...you are killing the pointer...but they both are still the same copy.....

Try adding one value to the first one BEFORE you do a set MyFoo1 =
nothing...and you will STILL find the 2nd instance will have that new
value...

You have to write code to copy the class......

--
Albert D. Kallal (Access MVP)
Edmonton, Alberta Canada
pl*****************@msn.com
http://www.members.shaw.ca/AlbertKallal

Apr 18 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.