Jump to content
  • Advertisement
Sign in to follow this  
IndyOfComo

The purpose of Clone()

This topic is 1742 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have tried Googling, haven't found an answer for this yet. I have found plenty of sites and questions which talk about the value of the ICloneable interface, the difference between shallow and deep cloning(which I didn't know about before, now I do)...  I have found sites which say "This is what Clone() does."

 

All well and good, but my basic question still isn't answered. WHY clone? At all. Forget the interfaces, forget the deep/shallow aspect....Why do it at all? In what kind of situation (instance is a bad synonym in this group :)  ) is cloning an object even useful?

 

Situation like this? A blob creature divides every 10 seconds; on a timer call clone() and add the new blob object to the list<creature>?

 

And if that's the kind of usefulness it has, then I'm guessing it's pretty pointless for something singular in your game, like say the field in a sports game.

Share this post


Link to post
Share on other sites
Advertisement

Clone is used for the "copy-on-write" concept.

 

Clone is useful if the original object is being referenced elsewhere, you want to make some changes, AND you want to leave the original copy alone.  So, you clone your object, then you're free to make changes to the clone without affecting the original.

 

Whether you need to Clone or not depends on how you've designed your codebase.  You can write large programs (games included) just fine without ever needing to clone anything.

 

A very basic example would be:  Say you have a level editor, and you've placed some objects on the map.  Each object has some customizable data that's different per instance (perhaps a switch has a link to the object it toggles).  Your editor supports copy/paste.  When you make a copy of one of those objects, you should clone it.  This lets the user change some properties of the new instance without affecting the original.

Edited by Nypyren

Share this post


Link to post
Share on other sites

Sometimes you want something equivalent to another thing, and don't care whether the copy was shallow or deep -- if it doesn't matter, shallow copy is preferable because it saves resources. Other times, you want something that's identical to, but distinct from, some other thing.

 

As Nypyren alludes, this is the basis of copy-on-write semantics. Its also the basis of the prototype pattern. Basically its useful anytime you want to copy and object, and you might want to modify the copy without affecting the original. 

Share this post


Link to post
Share on other sites

But is even then the generic "Clone" method from say Java right thing to use? I personally always felt it a lot better to essentially have my own CustomClone system that is very specific in what it does and does not do with the system only being used for those specific things.

 

E.g. in your level editor example, lets say a unit can be given a "defend this other unit" standing order.

 

Now you copy/paste just that unit. I suspect the correct thing to do is make the new unit have that standing order exactly the same.

 

Now say you select and copy both the unit with the defend order, and the unit it is defending. When you paste that I think the new defend unit should have its defend command defend the other unit you just copied, not the original, but that is not what clone gets you.

Edited by SyncViews

Share this post


Link to post
Share on other sites

In a nutshell, almost never.  Many authors, such as Exceptional C#'s author, Bill Wagner, basically say to never used ICloneable, unless you have a very very very good reason. Even the sceneraio Nypyren described would be better accomplished by implementing a copy() method.  This way you aren't forcing ICloneable on derived objects.

 

There is no ICloneable<T>... that is pretty telling of what Microsoft think of ICloneable.

 

 

Here is the direct summary advice from Wagner, and I think it's as succinct a description as you are going to here:

 


ICloneable does have its use, but it is the exception rather than rule. It’s significant that the .NET Framework did not add an ICloneable<T> when it was updated with generic support. You should never add support for ICloneable to value types; use the assignment operation instead. You should add support for ICloneable to leaf classes when a copy operation is truly necessary for the type. Base classes that are likely to be used where ICloneable will be supported should create a protected copy constructor. In all other cases, avoid ICloneable.

Edited by Serapth

Share this post


Link to post
Share on other sites


Now say you select and copy both the unit with the defend order, and the unit it is defending. When you paste that I think the new defend unit should have its defend command defend the other unit you just copied, not the original, but that is not what clone gets you.

 

If we're talking about a standard interface, then I can agree that you probably don't want to use it, and you certainly don't want to bend it into doing anything non-standard, lest you break assumptions used somewhere else in the system (A containers library is likely to make assumptions based on IClonable).

 

However, if we're talking about the concept of copy vs clone semantics, then I'd say that the example you give actually *is* the correct behavior, or more accurately, the beginning of it. This goes back to the copy-on-write / prototype pattern, by cloning the two units you get most of the way to what you want -- the unit being defended by the other maintains its own standing orders and other state, the unit that's doing the defending maintains its general standing orders (defend another unit) and other state. The only thing that needs to change is which unit it's defending -- Since you have a distinct clone that has taken on all other attributes, you just need to update the target. This re-wiring of the target necessarily has to take place at a higher level than the unit's Clone() method, firstly, because the unit should only ever have concrete knowlege about the unit its been assigned to defend, and secondly because the unit that it will defend doesn't, conceptually, exist yet -- they're being cloned together, after all. To do this all via Clone(), you'd have to put all that logic inside, and it clearly doesn't belong there. 

Share this post


Link to post
Share on other sites

I agree with Serapth.  I don't use ICloneable; I just write my own Clone methods which return the correct type.  Polymorphic cloning implies that your object is a heterogenous hierarchy - for example you've got a JSON-like nested Dictionary<string,object>.  In that case, you will probably have to write a separate set of cloning methods in a utility class instead of trying to shoehorn cloning into the objects themselves.

Share this post


Link to post
Share on other sites

I'd like to add my vote to the "in general don't use ICloneable" camp ... The reasons to avoid using or relying on the ICloneable interface is very simple:

  1.  An interface is a CONTRACT.

  2.  There is no single standard meaning of "Deep" copy or cloning.

  3.  Therefore this interface defines a very fuzzy contract, and noone can agree as to how it should be implemented in all cases, meaning it violates the ENTIRE REASON to have an interface in the first place.

 

So what SHOULD you do then?

  First, if someone else's code that you need to use, uses IClonable ... then of course you have to implement it ... its not your fault they made a bad choice, but just don't use it yourself if you don't have to.

  Second, when you need "Deep copies", "Cloning", "Template Instancing", "Forking", or any other Clone-like behavior in your code.  Create a SPECIFIC interface for that EXACT usage scenario.  Define it very clearly.  Implment it on each appopriate object consistently.  And use it as you intended.  But if you find you need another "similar" "deepish" copy ... with slightly different constraints, rules, or reasons.  Create a DIFFERENT interface.  It is fine for your classes that implement these interfaces to use a common private/protected method to do the heavy lifting when it needs to do the same work in each (Code duplicatation is BAD, so don't do it) - but the INTERFACE should be different if the CONTRACT is different.

 

Example of different contracts you might have in a game:

  1.  "Copying" 1 or more "objects" the user has selected in a map / level designer, so that the user can easily create a similar set.  This is "cloning", but don't use ICloneable.  Create a specific interface for your game object instances.

  2.  Creating a "Unit" instance from a "Unit Design" at one of the players "Factories".  This is not ICloneable, it is a different thing - and it is different than #1 above too.

  3.  "Copying" the entire game state, to allow the running of a "similation" to make chocies (ie, if the AI wants to simulate moves to evaluate their relative merit).  Cloning, but not ICloneable.

  4.  "Loading" a "Copy" of a saved scenario, so that the user may play it.  Obviously not ICloneable.

 

I could create a dozen more similar but diffrent examples.  Your game will probably have at least 1 and maybe half a dozen such cases by the time you have completed it.  But they will each just be independent custom interfaces, or custom methods of other interfaces you may have, such as your "IGameObject", "IGame", or "ISprite" interfaces.

 

Never sign poorly written contracts, never use poorly specified interfaces.

Edited by Xai

Share this post


Link to post
Share on other sites

In a nutshell, almost never.  Many authors, such as Exceptional C#'s author, Bill Wagner, basically say to never used ICloneable, unless you have a very very very good reason. Even the sceneraio Nypyren described would be better accomplished by implementing a copy() method.  This way you aren't forcing ICloneable on derived objects.
 
There is no ICloneable<T>... that is pretty telling of what Microsoft think of ICloneable.
 
 
Here is the direct summary advice from Wagner, and I think it's as succinct a description as you are going to here:


Indeed, and one of the MAIN reasons NOT to implement cloning is because: Is it a DEEP clone, or a shallow one? The "Clone()" method does not specify in any way which it is. Thus it is impossible for you to know, short of having a look at the code its self (which you presumably can if you're writing the code, but in a large code base this is cumbersome and slow...) Edited by Washu

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!