Where’s the Clone()?
The next design pattern I plan to tackle in ActionScript 3.0 is the Prototype Design Pattern. Getting started I ran into the clone() method in other languages like C#. As usual, that wasn’t much help. To my surprise, I found that several classes in ActionScript 3.0 have a clone() method such as the Rectangle class. However, while perfectly functional, cloning a rectangle with origins in the flash.geom namespace isn’t exactly what I had hoped for. (There’s no clone() method in the Shape class where I could make lots of clones of rectangle shapes I could put on the stage.) What I wanted was a way to clone objects.
Borrowing from Java
Buried in the Adobe ActionScript 3.0 Live Docs is a little note about cloning arrays. (see http://livedocs.adobe.com/flex/3/html/10_Lists_of_data_6.html) Using a method commonly found in Java programs, the note indicates that a deep copy clone is possible using this method. One can use concat() or slice() with no arguments to make a shallow copy. In most cases, GoF note that shallow copies will work fine, but for more complex structures a deep copy is required.
The docs list the key method as the following:
1 2 3 4 5 6 7 8 9 | import flash.utils.ByteArray; function clone(source:Object):* { var myBA:ByteArray = new ByteArray(); myBA.writeObject(source); myBA.position = 0; return(myBA.readObject()); } |
That’s a nice little piece of code and simple to understand. The clone() method creates a ByteArray that writes the object (an array) and then returns it by reading the object it just wrote. Moreover, it’s a deep copy and as such a true clone in that all of the parts are delivered and not just pointers.
A Cloning Class
Cloning an array is fine, and I even added a note in Live Docs first asking for an example and then provided one. (I’m not trying to befuddle those who screen comments on Live Docs—it’s just an added bonus.) What I really want to do is to clone an object, and since an array is an object, it seemed to be an easy enough task. So I took the basic algorithm and made it the key method of a Clone class. Here’s the code:
Clone.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package { import flash.utils.ByteArray; import flash.display.Sprite; public class Clone extends Sprite { private var cloneWork:ByteArray; public function Clone() { //Constructor } public function doClone(source:Object):* { cloneWork=new ByteArray(); cloneWork.writeObject(source); cloneWork.position = 0; return (cloneWork.readObject()); } } } |
Next, I created an object with lots of properties of different types—string, number and Boolean. Then, I tried cloning it, and it seemed to work. The following listing shows the client class that used the clone method—doClone() from the Clone class:
ObjectClone.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package { import flash.display.Sprite; public class ObjectClone extends Sprite { private var clone:Clone; private var webLanguages:Object; private var moreWeb:Object; public function ObjectClone() { webLanguages={}; webLanguages.flex="ActionScript 3.0"; webLanguages.dotNet="C#"; webLanguages.php="PHP"; webLanguages.inHtml="JavaScript"; webLanguages.bandWidth=2500000; webLanguages.usesFMS=true; for (var w:* in webLanguages) { trace("Property "+w+"="+webLanguages[w]); } trace("------------------------"); moreWeb=new Object(); clone=new Clone(); moreWeb = clone.doClone(webLanguages); for (var k:* in moreWeb) { trace("Property "+k+"="+moreWeb[k]); } } } } |
The following output shows that the cloned object has all of the properties and values of the original:
Property flex=ActionScript 3.0
Property dotNet=C#
Property usesFMS=true
Property php=PHP
Property inHtml=JavaScript
Property bandWidth=2500000
————————
Property flex=ActionScript 3.0
Property dotNet=C#
Property bandWidth=2500000
Property usesFMS=true
Property php=PHP
Property inHtml=JavaScript
The mystery is why the output is ordered the way it is. (If anyone knows, please send a comment.) All of the pieces to the objects are there in the clone, and they reflect the correct values of the original. The clone may seem a bit Frankenstein-ish, since the parts are in a different order, but the original seemed to move the parts around as well; so I’m not too concerned.
Next Stop: Prototype Design Pattern
Now that I have a working clone method for cloning objects, the next step will be working it into the Prototype pattern. The issue of serialization has not been broached here, but it is a topic I hope to take up in discussing the Prototype. Also, there’s not a lot of difference between an Object as used in this example and an associative array (ActionScript’s hash table equivalent). So, I may make it look more like an associative array rather than a plain vanilla object even though I like the idea of an object better. Also, I believe that using the Prototype Design Pattern beyond a simple example may require more work in the clone department to clone more sophisticated objects like MovieClips and Components.
Comments encouraged!!

When you iterate over properties in an object using for-in, and for-each, the order of those properties is explicitly not guaranteed. It’s part of the language spec, and I know I’ve seen it hidden in the docs somewhere.
I assume this keeps things simple for implementers to optimize memory and performance. People often expect that the properties will be accessed in the order they are added to the object, but it might be much faster to access them in a different order. Again, only guessing.
Hi Josh,
Your guess is spot on. Here it is right in the for..in statement AS 3.0 docs:
It’s all there then. The for..in loop just doesn’t return the properties in any particular order. So, it now makes perfect sense why both the original and clone had different orders from the order in which the properties were placed in the object.
Many thanks,
Bill
hi there, your website is just very nice, few people write about dp in AS3 …so your website is a great ressource for us.
Not a bad idea to use the ByteArray class when of course a clone() method doesn’t exeist already..
Do you advise the use of byteArray event though a clone() method already exist?
Hi Gropapa,
I don’t know if you know Jesse Warden, but when I was trying to decide whether to try and use the ObjectUtility.copy() method–in Flex– or use the clone() method by developing the Java-type code in the docs, he suggested that using the clone() method was better. It may have been the difference between a shallow and deep copy. Using clone() with the ByteArray class I was able to get a deep copy. I’m not sure whether that would be the case using copy() or an array method.
I’d really like to hear from anyone who’s used the ObjectUtility.copy() method to get a more in-depth idea.
Thanks,
Bill
What am I missing? (cool site BTW!)
> The problem with a shallow copy is that any changes to one will make changes in the other. That is, the property values of the copy cannot be changed without making the same changes in the original.
code:
output:
1,2,3,4,51,2,3,4,5
**********
1,2,3,4,5
1,new,3,4,5
JCG,
You’re quite right. I think I found where I may have tripped up in getting shallow copies right. On page 121 of GoF, they discuss a C++ member-wise copy and I took that to be a more general discussion of a shallow copies in the same section. In fact, GoF point out,
in talking about how SmallTalk generates a shallow copy by default. However, they go on to note that “cloning prototypes with complex structures usually requires a deep copy.”
In October I’ll be making a presentation at the OOPSLA Annual Conference, and while I’m there, I’ll talk to some people about the differences between deep and shallow copies in general. In the meantime I’d like to try and find out exactly how shallow and deep copies are made in ActionScript and how they affect cloning in the Prototype design pattern.
I made changes in the original short article on cloning to reflect the fact that shallow copies can be used for creating a Prototype.
Thanks again,
Bill
Serialization of AMF types really varies. AMF has a way of determining things and it may be a big-endian or little-endian scenario of how things are written and read. Oh, and if you really want to serialize a class in depth, use describeType to view the complete layout of a class instance, and call a corresponding IExternalizable method, such as writeUTF(), writeBoolean(), writeObject() etc on each member of the class and even to members of each member and so on. That would be a brute-force way to do it, but it would guarantee deep-copying.
Hi TK,
I looked at the Flex docs on IExternalizable, and as you say, it is certainly the interface to go with for a deep-deep copy. Also, I believe that in order to copy some of the more complex classes/UIs, etc., that’s what I’ll have to do. To get started, though, I’m going to use the simpler deep copy as described in the article. This would be the minimalist example so that we can see how everything works in the Prototype.
In the meantime, if you’d be interested in whipping up a little clone using your suggested method, we’d be giddy with gratitude.
Thanks a million,
Bill
P.S. With luck, I’ll be able to get a little time this week or next to put together a simple working example of a Prototype DP. (Work keeps getting in the way of fun.)
for the Prototype Pattern you may want to look at this blog post
http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html
now for AS3, because the language as kept his dynamic roots (dynamic and prototype statements), you can say that we do have the Prototype Pattern built in.
About cloning objects you also want to explore “is-like-a” and “has-like-a” relationships (instead of “is-a”/”has-a”)
something like that (sorry for the boring code)
—-
—-
so if you read a bit the post from Stege Yegge you will see that we have directly in the language this system of Properties Pattern aka Prototype Pattern
you can even inject an instance in the prototype to inherit its properties either at the object level or the prototype level
Hi Bill
First of all, congrats for this website, is a great resource. Second, if I understood right you are looking for a clone method that does a deep copy of a custom-sophisticated class. I guess this should work:
Of course the registerClassAlias method should be called only once, not every time you clone the class…but I was to lazy to write the entire class
Hope it helps you!
Cheers!
Hi Zw,
Wow! That was some comment. Thank you. I took a quick look at Steve’s blog and your listing (not boring to me!!) and I really appreciate it.
I’m still working on a Prototype ‘out in the open’ rather than the built-in one. However, that doesn’t mean I’m not planning on using the built-in Prototype; just waiting until I can build one from the ground up. In that way I feel I can fully understand what’s going on and use it whether it’s built-in or of my own making. However, your post will be used one way or the other!
Thanks,
Bill
Hi Radu,
Ok, now you’ve got me interested. The clone method I used is almost identical to yours, but the most important part, registerClassAlias() is not in the listing and it is a big difference. Using it, there’s no need for a parameter in the clone() method itself, but I’m not sure what you do to point to the object you want to clone.
Could you share with us the registerClassAlias() and how it is used with the clone()? That would be very interesting.
Kindest regards,
Bill
Hello Bill,
I’ve made a new example. The registerClassAlias allows you to recover the class after you are reading the ByteArray. So, in your example if you try to clone anything else than an Object you would get an runtime error (Coercion failed). Using registerClassAlias would solve that. Now, as I was writing the example I realized that maybe there is a way to clone the instance properties without itinerate through them (most of the properties like x,y, buttonMode etc of the sprite were preserved in the cloned object). Here is the example:
Hi Radu,
Thanks man. I like those methods you added (getDefinitionByName and getQualifiedClassName), and I want to try them out. Very interesting stuff.
Kindest regards & thanks again,
Bill
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
you find them in the flash.utils package:D
Regards
Radu