AS3 Sad bits #1: Deep copying or cloning

Pass by reference is great but if you need to make deep copies in AS3 you're alone.

UPDATE: This post is outdated, see:

Along with many great improvements in AS3 there are a few things that are frustrating.

While for some, a great programming language is on that has a very concise, elegant core and for others a more capable standard, some facilities really should be included in the language itself. Complex objects in AS3 are passed by reference, and it works almost all the time. At another times though, you must make a fresh new, deep copy of an object. An object where all of it's properties are unique new objects, recursively. That's why it makes sense to give developers a way to make deep copies. That's why python has the copy module.

AS3 can make copies of objects with the ObjectUtil module. But as it's documentation says, it will work for some objects, but not for others. The documentation doesn't go into much detail of what constitutes a good clonable object. It tells us that it won't work for UIComponent objects. Why not? it will later go on and recommend the "clone" method on these objects. But the clone method is a mystery in itself: it's not defined in a root object in the display list. Some objects implement it , some don't.

In a current project I stumbled upon the need to clone NetStream instances. No dice. No clone method. Ok, so I will implement it my self. Following this thread, it seems more people have ran into this issue. The work around is to copy ByteArray.writeObject. Great! Except that you'll loose typing information, making it somewhat useless. Now you must traverse the prototype hierarchy and copy that as well.

Sure, deep copying poses some questions: circular references and large data structures, but the first one can be resolved pretty easily and the second one, just let developers decide what's too large to copy.

This came as a shock because the new display list, with it's real node tree, where you can move objects freely along the tree would benefit a lot from a powerful clone method. It's useful to really duplicate a MovieClip (with all state preserved): current frame, transforms, filters, callbacks and all.

I'll just have to stop whining and code a well rounded class. Any finished implementations on this?

getting a third opinion

1.
Sam Wilson says at

No implementation here, but I do feel your pain and frustration with those little gotchas with as3, especially this one. I discovered this roadblock through using BulkLoader... loading in some crap and trying to assign 1 loaded-in movieclip to more than place on the stage. The author of BulkLoader mentions in the following link that someone trying to clone an mc (or other display item) is currently out of luck:

2.
Sam Wilson says at

How embarrassing, I just posted on your blog not realizing you are the author of BulkLoader. Lol, sorry my friend. It's getting late. BulkLoader is one of my favorite things in as3 btw. Keep up the excellent work.

3.
Arthur Debert says at

LOL, good one. Cheers yourself.

4.
cisnky says at

So did you manage to clone the netStream?

5.
Arthur Debert says at

Nope, the need wasn't there anymore, but I'd be curious to how it turns out.

Cheers

6.
cisnky says at

Trying it now. Not had much joy yet :)

7.
thebrain says at

Here's a way to deep clone objects in as3: http://blog.another-d-mention.ro/programming/how-to-clone-duplicate-an-object-in-actionscript-3/

8.
Arthur Debert says at

Hi The brain, this is very nice . This almost works. It's not really cloning, there are some situations where it won't work, namely if there is anything done on the constructor for that class.

There is no silver bullet for this, each solution has a different trade off, and none of them cover 100% of the use cases.

Cheers

9.
Agustin says at

Guess I can't take the easy path of cloning this time... :(

: LOL. I so empathise with you.

10.
sebtheweb says at

I clone a movie clip this way (works fine):

// extract the constructor var cloneFactory:Class = myMovieClip.constructor as Class;

// use constructor to create as many instances as you like var clone:MovieClip = new cloneFactory() as MovieClip;

Cheers, seb

11.
Bryn says at

I was looking for a way to use a loaded image twice in an AS3 project. After lots of hitting my head against google, I finally figured it out. I use bulkloader, so this seemed like a relevant place to post(Arthur feel free to relay my comment to a more appropriate spot if you like).

Immediately following loading an image you do this:

// grab the instance from bulkloader var img1:Bitmap = bulkLoader.getBitmap(loadedFile); // create a second bitmap and // set it's value equal to the bitmapDdata of the first. var img2:Bitmap = new Bitmap(img1.bitmapData);

12.
Arthur Debert says at

Hi Bryn.

Yeap, for images it is simple. BulkLoader itself can help you with that: bl.getBitmapData('bg.jpg');

Will create copies of the bitmap data as needed. This is only an issue if you need to clone Loader or MovieClip objects.

Best regards

13.
slopps says at

Wow...good info. I cannot fathom how this was left out of AS3...so frustrating.

To be clear, if a custom class extends MovieClip (or any DisplayObject) and you attempt to clone it, it will not work properly?

Sigh...guess I'll just have to recreate it from scratch. How annoying.

Thanks for BulkLoader...it's the best!

14.
danie says at

I opened a feature request for this. So go and vote for this: https://bugs.adobe.com/jira/browse/ASL-139

15.
daniel says at

Vote for it here, the previous one was a mistake https://bugs.adobe.com/jira/browse/SDK-27864

16.
Contus says at

I found your site very interesting and informative.

Have the last word





posted by
Arthur Debert

on

Tagged with:

16 comments so far.
Say something

Other months availabe in 2007

The complete blog archive

The latest entries

Subscribe to comments on this entry: rss feed

Cloud me:

Feeds: Entries rss feed Linksrss feed Worksrss feed

A Django joint. hosted on Slicehost