5Jun/0917
How to clone (duplicate) an object in ActionScript 3
For a project I needed to clone an object of unknown type. And by clone I mean to create a new instance of that same type and then fill out all its properties (including getters and setters) to mirror the original object.
Thanks to a friend, I discovered the describeType function in AS3. But this alone will only take care of the copying part. To create an object of the same type as another one we use getDefinitionByName.
Although Flash reflection is pretty basic, with a little work it will do the trick.
Get the application files.
Here's the code:
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 39 40 41 42 43 44 45 46 | < ?xml version="1.0" encoding="utf-8"?> <mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:local="*" creationComplete="init()"> </mx><mx :Script> < ![CDATA[ import mx.controls.Alert; private var source:DataObject = new DataObject(); private var cloneObject:DataObject; private function init():void { source.name = 'John Doe'; source.howMany = 4.5; source.when = new Date(0); source.complexProp = new DataObject(); source.complexProp.name = 'Name in sub-object'; cloneObject = UtilFunctions.clone(source) as DataObject; Alert.show("Clone:\nname = " + cloneObject.name + "\nhowMany = " + cloneObject.howMany + "\nwhen = " + cloneObject.when + "\ncomplexProp.name = " + cloneObject.complexProp.name); } /** * describeType will produce this (for a DataObject instance): * * <type name="DataObject" base="Object" isDynamic="false" isFinal="false" isStatic="false"> <extendsclass type="Object"/> <accessor name="isHandicap" access="writeonly" type="Boolean" declaredBy="DataObject"/> <variable name="howMany" type="Number"/> <accessor name="complexProp" access="readwrite" type="DataObject" declaredBy="DataObject"/> <variable name="name" type="String"/> <variable name="when" type="Date"/> * * */ ]]> </mx> |
And the UtilFunctions.as file:
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 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | package { import flash.utils.describeType; import flash.utils.getDefinitionByName; import flash.utils.getQualifiedClassName; public class UtilFunctions { public static function newSibling(sourceObj:Object):* { if(sourceObj) { var objSibling:*; try { var classOfSourceObj:Class = getDefinitionByName(getQualifiedClassName(sourceObj)) as Class; objSibling = new classOfSourceObj(); } catch(e:Object) {} return objSibling; } return null; } public static function clone(source:Object):Object { var clone:Object; if(source) { clone = newSibling(source); if(clone) { copyData(source, clone); } } return clone; } public static function copyData(source:Object, destination:Object):void { //copies data from commonly named properties and getter/setter pairs if((source) && (destination)) { try { var sourceInfo:XML = describeType(source); var prop:XML; for each(prop in sourceInfo.variable) { if(destination.hasOwnProperty(prop.@name)) { destination[prop.@name] = source[prop.@name]; } } for each(prop in sourceInfo.accessor) { if(prop.@access == "readwrite") { if(destination.hasOwnProperty(prop.@name)) { destination[prop.@name] = source[prop.@name]; } } } } catch (err:Object) { ; } } } } } |
by Evolvernie
Related posts:
- Serialize JavaScript object to JSON
- How to identify at runtime if the swf is in debug or release mode/build
- Neural networks in ActionScript 3
- Create professional Flex components
- Ho-To: Install Alchemy
August 4th, 2009 - 17:39
Evolvernie this is fantastic! I was having some really weird results using ByteArray.readObject()when trying to clone some objects and these classes have turned out to be an absolute life saver.
August 6th, 2009 - 09:53
Thanks a lot. I use it to set the proxyImage for DragManager.
It’s perfect!
BTW, which license does it apply? Can I use it freely?
August 6th, 2009 - 09:59
@CHEN Cheng
yes, you can use it however you want.
September 3rd, 2009 - 01:15
Whaou!!!! très très bon!!! Merci à toi! ça va me servir!
thanks a lot!!!
October 7th, 2009 - 16:18
Thanks. Works fine.
November 20th, 2009 - 11:44
really great, thx a lot!!
December 22nd, 2009 - 23:19
nice work. doesnt seem to work with Sound objects?
January 27th, 2010 - 08:03
Thank You for this, works with loaded bitmap
February 8th, 2010 - 18:45
Thx, works great and much appreciated!
February 25th, 2010 - 16:26
Nice! Your solution made fixing a showstopping problem on our project a no-brainer. Thank you!
March 30th, 2010 - 17:07
Made my day ! Thanks !
June 2nd, 2010 - 23:50
Awesome!! Just exactly what I was looking for.. thanks a ton
June 15th, 2010 - 21:29
I noticed that this will only work for Objects with optional or no arguments passed in the constructor. Also private properties with no setters will cause errors
June 16th, 2010 - 08:24
Well, you cannot know what parameters to use in the constructor and you don’t have access to private properties
June 17th, 2010 - 22:28
Compliments.
A problem: methods are not cloned =\
June 21st, 2010 - 18:22
a new object of same type is created. the methods are there.
July 19th, 2010 - 15:55
This is a great class.
Sadly it does not work with sound objects