Hi Lasse,
Thanks for the post. It was really insightful.
I'll keep it in mind, next time I develop a more complex structure.
Many thanks,
Andre
Lasse Vågsæther Karlsen wrote:[color=blue]
>
ahaupt@gmail.com wrote:[color=green]
> > Hi all,
> >
> > I'm implementing the Clone() method through the ICloneable interface[/color]
> <snip>
>
> Doing a "deep clone" is a serious matter and needs specific knowledge of
> the target types, at least in a lot of scenarios. Cloning any type of
> object is not that easy.
>
> Let me give you an example.
>
> Suppose you have the following classes:
>
> - Order
> - OrderLine
>
> Their relationships are:
>
> - An Order can hold references to many OrderLine objects
> - An OrderLine object holds a reference to the Order that its a part of
>
> Now...
>
> If you want to clone an order, you would:
>
> - Clone the Order
> - Clone all the OrderLines attached to it and attach them to the cloned
> order
> - Fix up the references (so that the cloned OrderLine's reference to its
> order points to the new, cloned, order)
>
> If you want to clone an orderline, you would:
>
> - Clone the orderline, leaving the reference to its order in place for
> the new line (in other words, you duplicate a line which ends up
> attached to the same order as the original)
>
> This means that the process of cloning an orderline depends on wether
> you are only cloning an orderline or wether you are cloning the whole order.
>
> If you implement "deep cloning" in both without knowledge about where
> you started you might end up with:
>
> - Call .Clone on Order, produces new Order object and proceeds to call
> .Clone on each OrderLine and attaching them to the new Order object
> - For each .Clone call on each OrderLine, you clone that object, which
> in turn clones the Order again, going back and produces a new Order
> - Repeat ad nauseum
>
> In other words, you can't write the cloning process for the orderline
> without knowledge about the objects around it and what you are actually
> cloning (where you started in other words).
>
> Cloning is something you need to work into a class hierarchy as a whole
> and you cannot do it separately for all the objects, or you will get a
> broken implementation.
>
> To add to the above problem, add a Customer to the whole thing. A Order
> or OrderLine might contain a reference to the Customer, and possibly the
> Customer might contain reference to all his orders. What happens if:
>
> - You clone the order (leave it attached to the same customer)
> - You clone the customer (clone all orders which will use a different
> customer reference)
>
> I've looked at several ways to implement cloning and have found that the
> following three ways seems to work ok and leave little doubt about what
> is actually happening:
>
> 1. Use a mechanism with attributes to tag properties in a class that
> should be "fixed up" during cloning, in such a way that I can know what
> to do depending on what kind of object the cloning process was started
> from (ie. I can detail what happens if I clone a Customer vs. a Order
> vs. a OrderLine). The attributes still need to be written so that they
> cover each scenario (all the possible starting points for cloning)
> 2. Use a separate cloning helper class for the hierarchy with methods
> that clearly detail what they do (CloneCustomer, CloneOrder,
> CloneOrderLine) and leave the cloning mechanism completely out of the object
> 3. Give the Clone methods the type of the initial class I called .Clone
> on so that they know what to clone and what to copy (this is just a
> non-attribute version of #1).
>
> The ICloneable interface gives you a lot of questions, many of which the
> answer to is "ICloneable is not enough" so I've decided that I won't use
> it for my own objects except for trivial scenarios (ie. objects which
> clearly aren't meant to participate in big hierarchies and graphs).
>
> --
> Lasse Vågsæther Karlsen
>
http://www.vkarlsen.no/
> mailto:lasse@vkarlsen.no
> PGP KeyID: 0x2A42A1C2[/color]