13.11 深度拷貝一個ArrayCollection集合
13.11.1 問題
須要拷貝一個索引數組裏的全部項或者從一個對象建立一個新對象。
13.11.2解決
使用mx.utils.ObjectUtil.copy方法
13.11.3討論
正如演示那樣,copy一個對象僅僅是爲新對象建立了一個指針。意味着對第一個對象值的任何改變都會反映到第二個對象上。
var objOne:Object =
{name:"foo", data:{first:"1", second:"2"}};
var objTwo = objOne;
objOne.data.first = "4";
trace(objTwo.data.first);//traces 4
相反若是咱們想要copy一個對象的所有到另外一個對象中,使用mx.utils.ObjectUtil類的copy方法。該方法接受一個對象作爲參數而返回一個在內存的新位置的此對象的深度拷貝。
這就意味着該對象的任何屬性被copy而再也不是引用原始對象相同位置的屬性。以下使用此方法:
var objTwo = mx.utils.ObjectUtil.copy(objOne);
此copy方法工做機制是經過原對象建立一個ByteArray,而後再把ByteArray寫入一個新對象,以下所示:
var ba:ByteArray = new ByteArray();
ba.writeObject(objToCopy);
ba.position = 0;
var objToCopyInto:Object = ba.readObject();
return objToCopyInto;
這樣原來的例子就能夠如期的執行:
var objOne:Object = {name:"foo", data:{first:"1", second:"2"}};
var objTwo = objOne;
var objThree = mx.utils.ObjectUtil.copy(objOne);
objOne.data.first = "4";
trace(objTwo.data.first);//traces 4
trace(objThree.data.first);//traces 1, which is the original value
爲了copy一個特定類型的對象爲一個新對象存在必定難度。下面的代碼會拋出一個錯誤:
var newFoo:Foo = ObjectUtil.copy(oldFoo) as Foo;
Flash Player並不知道如何把ByteArray轉換爲指定的類型。經過ByteArray,對象被序列化爲AMF 二進制數據,這種方式和Flash Remoting中的一致。
爲了反序列化此數據對象,該類型必須經過flash.net.registerClassAlias方法向Flash Player註冊。此方法註冊該類,以便該類的實例對象均可以從二進制反序列化回原對象。
registerClassAlias 須要2個參數:
public function registerClassAlias(aliasName:String, classObject:Class):void
第一個參數是此類的全類名,第二個參數是類型爲Class的一個對象。全類名就是相似以下的mx.containers.Canvas or com.oreilly.cookbook.Foo.
在這裏的例子中,拷貝對象時既不知道全類名也不知道該類的一個引用。幸運的是,flash.utils.getQualifiedClass會返回參數傳入的對象的全類名,而flash.utils.getDefinitionByName
返回傳入的對象的類引用。經過使用這2個方法,你能夠註冊任何對象的類:
private function copyOverObject(objToCopy:Object, registerAlias:Boolean = false):Object
{
if(registerAlias) {
var className:String = flash.utils.getQualifiedClassName(objToCopy);
flash.net.registerClassAlias(className,
(flash.utils.getDefinitionByName(className) as Class));
}
return mx.utils.ObjectUtil.copy(objToCopy);
}
如今一個強類型對象的ArrayCollection就能夠經過把集合中的每一個對象傳給copyOverObject方法正確的拷貝啦:
private function copyOverArray(arr:Array):Array {
var newArray:Array = new Array();
for(var i:int; i<arr.length; i++) {
newArray.push(copyOverObject(arr[i], true));
}
return newArray;
}
var ac:ArrayCollection = new ArrayCollection([{name:'Joseph', id:21}, foo,
{name:'Josef', id:81}, {name:'Jose', id:214}]);
var newAC:ArrayCollection = new ArrayCollection(copyOverArray(ac.source));
值得注意的是,若是僅僅是經過mx.utils.ObjectUtil.copy來拷貝這2個ArrayCollection,那麼原始ArrayCollection中的全部數據也會存在於新拷貝的ArrayCollection中。可是關於每一個對象的類信息將不存在,任何企圖
把該集合中一個對象強制轉化爲某一指定類型都將致使一個錯誤或空值。
譯者注:
1.實驗代碼1
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();">
<mx:Style>
Application{fontSize:12px;}
</mx:Style>
<mx:Script>
import mx.controls.Alert;
public function alertObj():void
{
var objOne:Object ={name:"張三", data:{first:"張", second:"三"}};
var objTwo:Object = objOne;
objOne.data.first = "李";//對原始對象的修改,也會在新對象反應出來
Alert.show(objTwo.data.first);//輸出 李
}
</mx:Script>
</mx:Application>
2。實驗代碼2--深拷貝
<?xml version="1.0" encoding="utf-8"?>
<!--對象的深度拷貝-->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();">
<mx:Style>
Application{fontSize:12px;}
</mx:Style>
<mx:Script>
import mx.controls.Alert;
import mx.utils.ObjectUtil;
public function alertObj():void
{
var objOne:Object ={name:"張三", data:{first:"張", second:"三"}};
var objTwo:Object =ObjectUtil.copy(objOne);//關鍵代碼
objOne.data.first = "李";//對原始對象的修改,不會影響第二個
Alert.show("objOne="+objOne.data.first+"\nobjTwo="+objTwo.data.first);//
}
</mx:Script>
</mx:Application>
3.對ArrayCollection深度拷貝
<?xml version="1.0" encoding="utf-8"?> <!--特定類對象的深度拷貝--> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="alertObj();"> <mx:Style> Application{fontSize:12px;} </mx:Style> <mx:Script> <![CDATA[ import mx.controls.Alert; import mx.utils.ObjectUtil; import mx.collections.ArrayCollection; public function alertObj():void { var zl:Object={name:"趙六",age:29}; var ac:ArrayCollection = new ArrayCollection([ {name:'張三', age:20}, zl, {name:'李四', age:31}, {name:'王五', age:27} ]); var newAC:ArrayCollection = new ArrayCollection(copyOverArray(ac.source)); //能夠以下驗證下 //ac[2].name = "改變"; //Alert.show(newAC[2].name); } //對一個對象數組深度拷貝 private function copyOverArray(arr:Array):Array { var newArray:Array = new Array(); for(var i:int;i<arr.length; i++){ newArray.push(copyOverObject(arr[i], false));//深度拷貝每一個元素 } return newArray; } //對對象深度拷貝 private function copyOverObject(objToCopy:Object, registerAlias:Boolean = false):Object { if(registerAlias) { var className:String = flash.utils.getQualifiedClassName(objToCopy); flash.net.registerClassAlias(className,(flash.utils.getDefinitionByName(className) as Class)); } return mx.utils.ObjectUtil.copy(objToCopy); } ]]> </mx:Script> </mx:Application>