novice question: shallow and deep copies 
Author Message
 novice question: shallow and deep copies

I'm struggling with shallow vs deep copies. The explanations
I've read just aren't sinkimg in. Anyone else want to
try to break through a dense skull? When would you
want to use shallow vs deep copying? Thanks for the help.



Tue, 29 Jul 1997 08:55:22 GMT  
 novice question: shallow and deep copies

Quote:

>I'm struggling with shallow vs deep copies. The explanations
>I've read just aren't sinkimg in. Anyone else want to
>try to break through a dense skull? When would you
>want to use shallow vs deep copying? Thanks for the help.

Here's a simple example that comes up often in varying forms.  Let's say
you are building an ordering system to manage Guiness Peat Aviations fleet
of hundreds of jet aircraft.  You need to order hundreds of parts for each
aircraft from thousands of vendors worldwide.

An order object has references to detail part item objects.  Each order may
have hundreds of parts.

Something on the order changes.  The system requires you to maintain all
historical versions of the orders.

You copy the order object with the reference OIDs to detail item and change
a date or address.  You do not touch the detail items or create any new
ones.  This is a shallow copy, then update of shallow copy.

You are an inexperienced programmer and select a deep copy method to do
this.  You copy the order and all the detail objects that are referenced.
The network goes down by running out of disk space.  Nobody can figure out
why but they are tracing your tracks.  You're in deep copy ...

Jeff Sutherland
"C++ runs slightly faster than Smalltalk but a lot later!"



Tue, 29 Jul 1997 21:17:04 GMT  
 novice question: shallow and deep copies

Quote:
> I'm struggling with shallow vs deep copies. The explanations
> I've read just aren't sinkimg in. Anyone else want to
> try to break through a dense skull? When would you
> want to use shallow vs deep copying? Thanks for the help.

 All Objects are pointers.
shallowCopy does a copy from the object itself,
 but not from their instance-variables.
deepCopy makes a copy from the object itself and of all
 instance-variables in it, so it takes much more ram on
 the sytem to store.
To test this the  =  and == you can use.
== ...this is the same pointer !

Normally shallowCopy is used.
deepCopy: If you want do make a copy from a collection,
 which should have no connection with the old collection and
 if you do not want a change in the old collection
 if you change the elements of the new collection (with at:put:)

    I hope, that is is o.k. what i said ??
--



Mon, 04 Aug 1997 00:46:32 GMT  
 novice question: shallow and deep copies

Quote:



>> >I'm struggling with shallow vs deep copies.

>> The main difference is the following:
>> shallow copy produces a new reference to the same object
>> deep copy creates a new instance

>> e.g.
>> b := a shallow copy.
>> a change_some_value.

>> now b has the same changed value as a

>> if you perform a deepcopy, the values of b will not change if you change
>> the values of a
>Ummm...., not being a real ST maven, I don't think so.  The real pros will
>probably jump in, but hey let me try...  So from one newbie to another...
>Shallow copy does NOT give a new reference to the same object.  That is
>merely done with the :=, i.e.
>a := AnObject new init.
>b := a.
>Now b and a are both references to the same object.
>c := a shallowCopy.
>c now points to a new object, BUT c is the same class as a AND all of c's
>instance variables point to the same objects as a.  If these are foo and
>bar which are set with the ever popular setter/getter routines #foo: ,
>#foo, #bar: , and #bar, then:
>a foo: aFoo; bar: aBar.
>c := shallowCopy a.
>a foo: anotherFoo.
>d := shallowCopy a.
>Now a, c, and d all point to different objects.  All three have the bar
>instance variable pointing to the same object (aBar).  However, the foo
>instance variable in c points to aFoo (a's original Foo when c was created
>by the #shallowCopy) and a and d point to anotherFoo.
>So, a shallow copy makes a New object whose instance variables are the
>same as the source object's.
>So what's a deepCopy?  Trouble, if my reading of some past threads are any
>indication, but follow along with me.  In the previous example if you were
>to make a change to the object (aBar), this would effect the behavior of
>all of the objects (a, c, and d) that have it as their bar instance.  How
>could
>you make a copy of an object that would break this perhaps undesireable
>connection?  This is what deepCopy is supposed to produce, and the way it
>does it is by sending a "copy" command to all the instance variables.
>That is if a, c, and d are all members of the Bletch class, the Bletch may
>have defined a method.
>deepCopy
>        | newBletch |
>        newBletch := Bletch new init.
>        newBletch foo: (self foo copy);
>                bar: (self bar copy).
>        ^newBletch.
>This is in contrast to
>shallowCopy
>        | newBletch |
>        newBletch := Bletch new init.
>        newBletch foo: (self foo);
>                bar: (self bar).
>        ^newBletch.
>(I apologize for the bad practices in the above, my actual ST codeing is
>pretty rusty).  Now of course, these routines are special code for the
>Bletch class.  In actuality there is support in Object that will
>automagically handle all the named and ennumerated instance variables for
>you.
>Were you paying attention to a little problem in the above though?  In the
>deepCopy method what I sent was a #copy message.  I have seen some
>ambiguity over whether this by default should actually be a #deepCopy, or
>#copy (which
>usually defaults to #shallowCopy) but you can override that for the
>particular classes of the *instances* to #deepCopy or whatever your little
>heart desires.  The advantage of ST.

There is lot of confusion here, so here it is:

  A shallow copy gives you a new object, which shares all instance variables
with the old one. A deep copy gives a new object and also new instance
variables. This definition is recursive. If the instance variables are complex
objects by themselves, their copies might be deep or shallow, so in effect
there aren't just 2 kinds of copy, but many. It really depends on how deep you
want your copy to be.

  Till now it was just general definitions, that apply to any object system.
Now to implementation. Older versions of PPS Smalltalk implemented shallowCopy
and deepCopy. In VW deepCopy has been removed (I believe it has been done
earlier in ObjectWorks 4.0, but it does not really matter) and it is up to
the user to implement a deep copy.

If you inspect copy in Object, you'll notice it is implemented as:

copy
   ^self shallowCopy postCopy

shallowCopy is a primitive that answers a new shallow copy of the object.

postCopy is implemented as ^self, but the comment there explains it all. It says
this is a method intended to be sent to the newly created instance to implement
a real copy.
Subclasses do implement copy (a fully deep one or partially deep one) by
reimplementing postCopy to copy their instance variables. They should never
reimplement copy.

You can find many examples of that in the base image. Look at:

CharacterAttributes >> postCopy

        super postCopy.
        attributes := attributes copy.
        defaultQuery := defaultQuery copy

By having each of your objects implement postCopy you get a recursive deep copy,
no matter how complex your object is.

I had only one problem with this approach. Collection classes in the VW image
do not implement postCopy, so if you have collections in your object structure
the chain of postCopy sends is broken. To overcome this you must either create
your own subclass of the collection, that implements postCopy (adding postCopy
to the base collection class is a bad idea because of side effects) or have the
object that has a collection as an instance variable iterate over the collection
in its postCopy and send copy to the elements of the collection. This might
become messy if the elements of the collection are collections by themselves...

---------------------------------
  Uri Eshkar    Boole & Babbage
  Voice:        (408)526-3418
  Fax:          (408)526-3055



Mon, 04 Aug 1997 03:11:04 GMT  
 novice question: shallow and deep copies




: >> >I'm struggling with shallow vs deep copies.
: >>
: >> The main difference is the following:
: >> shallow copy produces a new reference to the same object
: >> deep copy creates a new instance
: >>
: >> e.g.
: >> b := a shallow copy.
: >> a change_some_value.
: >>
: >> now b has the same changed value as a
: >>
: >> if you perform a deepcopy, the values of b will not change if you change
: >> the values of a

: >Ummm...., not being a real ST maven, I don't think so.  The real pros will
: >probably jump in, but hey let me try...  So from one newbie to another...

: >Shallow copy does NOT give a new reference to the same object.  That is
: >merely done with the :=, i.e.
: >a := AnObject new init.
: >b := a.
: >Now b and a are both references to the same object.
: >c := a shallowCopy.
: >c now points to a new object, BUT c is the same class as a AND all of c's
: >instance variables point to the same objects as a.  If these are foo and
: >bar which are set with the ever popular setter/getter routines #foo: ,
: >#foo, #bar: , and #bar, then:
: >a foo: aFoo; bar: aBar.
: >c := shallowCopy a.
: >a foo: anotherFoo.
: >d := shallowCopy a.

: >Now a, c, and d all point to different objects.  All three have the bar
: >instance variable pointing to the same object (aBar).  However, the foo
: >instance variable in c points to aFoo (a's original Foo when c was created
: >by the #shallowCopy) and a and d point to anotherFoo.

: >So, a shallow copy makes a New object whose instance variables are the
: >same as the source object's.

: >So what's a deepCopy?  Trouble, if my reading of some past threads are any
: >indication, but follow along with me.  In the previous example if you were
: >to make a change to the object (aBar), this would effect the behavior of
: >all of the objects (a, c, and d) that have it as their bar instance.  How
: >could
: >you make a copy of an object that would break this perhaps undesireable
: >connection?  This is what deepCopy is supposed to produce, and the way it
: >does it is by sending a "copy" command to all the instance variables.
: >That is if a, c, and d are all members of the Bletch class, the Bletch may
: >have defined a method.

: >deepCopy
: >        | newBletch |
: >        newBletch := Bletch new init.
: >        newBletch foo: (self foo copy);
: >                bar: (self bar copy).
: >        ^newBletch.

: >This is in contrast to

: >shallowCopy
: >        | newBletch |
: >        newBletch := Bletch new init.
: >        newBletch foo: (self foo);
: >                bar: (self bar).
: >        ^newBletch.

: >(I apologize for the bad practices in the above, my actual ST codeing is
: >pretty rusty).  Now of course, these routines are special code for the
: >Bletch class.  In actuality there is support in Object that will
: >automagically handle all the named and ennumerated instance variables for
: >you.

: >Were you paying attention to a little problem in the above though?  In the
: >deepCopy method what I sent was a #copy message.  I have seen some
: >ambiguity over whether this by default should actually be a #deepCopy, or
: >#copy (which
: >usually defaults to #shallowCopy) but you can override that for the
: >particular classes of the *instances* to #deepCopy or whatever your little
: >heart desires.  The advantage of ST.

: There is lot of confusion here, so here it is:

:   A shallow copy gives you a new object, which shares all instance variables
: with the old one. A deep copy gives a new object and also new instance
: variables. This definition is recursive. If the instance variables are complex
: objects by themselves, their copies might be deep or shallow, so in effect
: there aren't just 2 kinds of copy, but many. It really depends on how deep you
: want your copy to be.

:   Till now it was just general definitions, that apply to any object system.
: Now to implementation. Older versions of PPS Smalltalk implemented shallowCopy
: and deepCopy. In VW deepCopy has been removed (I believe it has been done
: earlier in ObjectWorks 4.0, but it does not really matter) and it is up to
: the user to implement a deep copy.

: If you inspect copy in Object, you'll notice it is implemented as:

: copy
:    ^self shallowCopy postCopy

: shallowCopy is a primitive that answers a new shallow copy of the object.

: postCopy is implemented as ^self, but the comment there explains it all. It says
: this is a method intended to be sent to the newly created instance to implement
: a real copy.
: Subclasses do implement copy (a fully deep one or partially deep one) by
: reimplementing postCopy to copy their instance variables. They should never
: reimplement copy.

: You can find many examples of that in the base image. Look at:

: CharacterAttributes >> postCopy

:       super postCopy.
:       attributes := attributes copy.
:       defaultQuery := defaultQuery copy

: By having each of your objects implement postCopy you get a recursive deep copy,
: no matter how complex your object is.

: I had only one problem with this approach. Collection classes in the VW image
: do not implement postCopy, so if you have collections in your object structure
: the chain of postCopy sends is broken. To overcome this you must either create
: your own subclass of the collection, that implements postCopy (adding postCopy
: to the base collection class is a bad idea because of side effects) or have the
: object that has a collection as an instance variable iterate over the collection
: in its postCopy and send copy to the elements of the collection. This might
: become messy if the elements of the collection are collections by themselves...

: ---------------------------------
:   Uri Eshkar  Boole & Babbage
:   Voice:      (408)526-3418
:   Fax:                (408)526-3055

Uri has it right.  My advise though, is to think of shallow and deep
copies in the same way you think of printOn's.  Sure you inherit it, but
if you want it to work correctly with your class, override it and write
one tailored to your own class.  This way you always know what you are
getting.  From the amount of confusion on this subject, writing your own
makes even more sense when alot of people are unclear on what the
inherited shallow and deep copies do anyway!  

Kevin
--
 ______________________________________________________




*______________________________________________________*



Mon, 04 Aug 1997 13:44:13 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. shallow copy vs. deep copy

2. Method literals and deep/shallow copy

3. shallow/deep binding question

4. Deep vs. Shallow binding

5. Help understanding deep and shallow equality

6. deep and shallow copy, what does the 'copy' method do ?

7. CLOS shallow copy

8. thinkings on shallow copy

9. shallow copy's

10. Custom Deep Copy

11. Deep Copy Needed

12. ABC newbie: How do I use deep assignment to copy records

 

 
Powered by phpBB® Forum Software