self shallowCopy postCopy

Boris Gaertner Boris.Gaertner at gmx.net
Wed Oct 19 05:02:42 UTC 2005


From: "stéphane ducasse" <ducasse at iam.unibe.ch>

> So I was thinking that it may be good to think if we want to introduce
> the same mechanism than in vw because it make a lot of sense to me.
>
> Object>>copy
>      self shallowCopy postCopy
>
> Object>>postCopy
>      ^ self
> Object>>shallowCopy
>      <prim>
>
> then the classes can decide how they implement their own copy
> overriding postCopy
>

postCopy is designed to remove the unwanted structure sharing
that is sometimes introduced by #shallowCopy. In our current Squeak
image, we do not use postCopy. Instead, we prefer
to redefine #copy.

Have a look at these two examples:

 Set>>copy
copy
 ^ self shallowCopy withArray: array shallowCopy

Dictionary>>copy
copy
 "Must copy the associations, or later store will affect both the
original and the copy"

 ^ self shallowCopy withArray:
  (array collect: [:assoc |
      assoc ifNil: [nil]
          ifNotNil: [Association key: assoc key
                            value: assoc value]])


To get rid of these methods, we can write:

* in Set:
  postCopy
    array := array shallowCopy

*in  Dictionary:
  postCopy
  array := array collect: [:assocOrNil |
               assocOrNil shallowCopy
           ].

With these changes, we can also drop  Set>>withArray:

For subclasses of Model, it may be desireable to have

postCopy
   self breakDependents.


By the way: It is obvious that a dictionary and its
copy should not have shared associations. However,
VisualAge for Smalltalk manages to redefine copy
for dictionaries and to preserve unwanted structure
sharing! That is really great!
-------------------------------------------


Method shallowCopy itself has a very strict definition:

For an object that is not an identity object, shallowCopy answers
a new instance that shares the values of its instance variables with
the message receiver.

For lovers of assertions, the properties of a shallow copy
can be expressed in this way:

When called with an instance and its shallow copy, the following block
answers  true :

[:instance :shallowCopy |
   instance class == shallowCopy class
     and:
       [instance instSize = shallowCopy instSize]
     and:
       [instance basicSize = shallowCopy basicSize]
     and:
       [(1 to: instance instSize)
           allSatisfy:
              [:idx | (instance instVarAt: idx) == (shallowCopy instVarAt:
idx)]
       ]
     and:
       [(1 to: instance basicSize)
           allSatisfy:
              [:idx | (instance basicAt: idx) == (shallowCopy basicAt: idx)]
       ]
]


(Please choose a font that clearly separates two equal signs in sequence!)

Greetings
Boris




More information about the Squeak-dev mailing list