Reputation: 113
I have a displayobject that has a bunch of properties. What I want to do is to clone this class. I understand it's not possible to do a deep copy of a custom class in AS3 so I have resorted to just copying the properties and then through a clone method create a new instance that has the same exact properties as the original.
I'm having some trouble getting all the properties of the displayobject. Sure I can just call each var one by one and putting it in an array and return that array to the clone like this:
function clone():Array
array.push(displayObject.x);
array.push(displayObject.y);
array.push(displayObject.price);
return array;
But that's not really Object Oriented. So I'm looking for way to get all object properties, which then I will put those properties in a new object.
Oh and I'm running on AS3 for Air not Flex, so I can't use the mx.utils.ObjectUtil, which is a way to do this.
Upvotes: 0
Views: 446
Reputation: 2435
package
{
import flash.display.Sprite;
import flash.utils.Dictionary;
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
public class DynamicClone extends Sprite
{
public function DynamicClone()
{
var p1 : Player = new Player;
p1.name = "Simsoft";
p1.hiddenAccessor = 10;
var p2 : * = clone( p1 );
// p2 is a Player instance
trace(getQualifiedClassName( p2 )); // Player
// p1 and p2 are not the same instance
trace(p1 == p2); // False
// But public properties are cloned
trace(p2.name); // Simsoft
trace(p2.hiddenAccessor); // 10
}
public function clone( source : Object, cloneGetSet : Boolean = true) : *
{
if( !source)
return null;
if( source is Array || source is Vector.<*> || source is Vector.<uint> || source is Vector.<int> || source is Vector.<Number> || source is Vector.<Boolean>)
return source.concat();
var newInstance : Object = new ( source.constructor );
// Copy dynamic var
for(var dynamicVar : String in source)
newInstance[ dynamicVar ] = source[ dynamicVar ];
var typeDescription : XML = describeType( source );
// Copy variables
for each(var variable : String in typeDescription..variable.@name)
newInstance[ variable ] = source[ variable ];
// Copy getter / setter
if(cloneGetSet)
for each(var getset : String in typeDescription..accessor.(@access == "readwrite").@name)
newInstance[ getset ] = source[ getset ];
return newInstance;
}
}
}
internal class Player {
// Will be clone
public var name : String;
// Won't be clone
private var _score : uint;
// Will be clone throught getter/setter
private var _hidden : uint;
// Can be clone because we have a getter and a setter
public function get hiddenAccessor():uint
{
return _hidden;
}
public function set hiddenAccessor(value:uint):void
{
_hidden = value;
}
}
Upvotes: 0
Reputation: 2101
You can't copy private property. You can use ByteArray to copy properties
Dog is the target class to be clone
public class Dog {
public function Dog()
{
}
public function setName($name:String):void {
name = $name;
}
public var subDogs:Array = [];
public var age:int;
private var name:String;
}
And here is how to clone
var dog:Dog = new Dog();
dog.subDogs.push(new Dog());
dog.setName("puppy");
dog.age = 15;
registerClassAlias("vo.Dog", vo.Dog);
var dogA:Object = CloneUtil.copy(dog);
var d:Dog = copy(dog) as Dog;
private function copy(source:Object):* {
var ba:ByteArray = new ByteArray();
ba.writeObject(source);
ba.position = 0;
return ba.readObject();
}
Upvotes: 1