本文共 4845 字,大约阅读时间需要 16 分钟。
今天在天地会看见一篇帖子,关于深度拷贝对象的,很有感触,于是自己又就此做了一些细致的研究。原帖:
我们重点讨论一个数据对象的拷贝,而非显示对象的拷贝,因为Flash的显示对象是无法做到真正的深度拷贝的。
这里说的数据对象呢,一般是一个存储数据的VO类对象。
相信大部分人都知道用下面这种方法来进行对象的拷贝。
常规方法,简单,但不全面.
public function clone(sourceObj:*):*{ var b:ByteArray = new ByteArray(); b.writeObject(sourceObj); b.position = 0; return b.readObject();}
文章开始提到的天地会的帖子的方法有所改进,但是也有弊端,对于类里的对象(复合类对象)无法做到拷贝,于是我重新写了一个方法,能够完全的拷贝对象里的除显示对象以外的所有数据型变量。(至少经过测试,目前我是这么认为,如果有相左的发现,请告知,不胜感激)
代码如下:
package com.gdlib.util{ import flash.net.registerClassAlias; import flash.utils.ByteArray; import flash.utils.describeType; import flash.utils.getDefinitionByName; import flash.utils.getQualifiedClassName; import flash.utils.getTimer; /** * Object 工具类. * @author Jack * Email: lovewqcm520@gmail.com */ public class ObjectUtil { private static var aliasList:Array = []; /** * 复制一个对象 * @param sourceObj 要复制的源对象 * @param deep 是否对对象进行AMF序列化以后再深度复制 * @return */ public static function clone(sourceObj:*, deep:Boolean=true):* { if(!sourceObj) return null; var lastTime:Number = getTimer(); if(deep) { // 得到 sourceObj的类名 var qualifiedClassName:String = getQualifiedClassName(sourceObj); if(aliasList.indexOf(qualifiedClassName) == -1) { // e.g com.gdlib.test::RegisterClassAliasTest var packageName:String = qualifiedClassName.replace("::", "."); // 得到 sourceObj的类的类定义 var classType:Class = getDefinitionByName(qualifiedClassName) as Class; // 注册此别名和类 if(classType) { registerClassAlias(packageName, classType); aliasList.push(qualifiedClassName); trace("register class", packageName); } // 注册类公共属性(如果是复合类) registerVariables(sourceObj); } } // 复制此对象 var b:ByteArray = new ByteArray(); b.writeObject(sourceObj); b.position = 0; trace("Clone object takes", getTimer()-lastTime, "ms.\n"); return b.readObject(); } /** * 注册某个类的公共属性(如果是复合类)所属的类的别名. * @param sourceObj */ private static function registerVariables(sourceObj:*):void { // 注册类公共属性(如果是复合类) var xml:XML = describeType(sourceObj); var variable:XML; var variableType:String; var variablePackageName:String; var variableClassType:Class; var variableXml:XMLList; if(sourceObj is Class) variableXml = xml.factory.variable; else variableXml = xml.variable; //// //// //// // for each (variable in variableXml) { variableType = variable.@type; if(variableType.indexOf("::") != -1) { if(aliasList.indexOf(variableType) == -1) { // "flash.geom::Point" 转换为 "flash.geom.Point" variablePackageName = variableType.replace("::", "."); variableClassType = getDefinitionByName(variableType) as Class; // 注册此别名和类 if(variableClassType) { registerClassAlias(variablePackageName, variableClassType); registerVariables(variableClassType); aliasList.push(variableType); trace("register variable", variablePackageName); } } } } } }}// ////
使用方法:
var source:RegisterClassAliasTest = new RegisterClassAliasTest();var result:RegisterClassAliasTest = ObjectUtil.clone(source); trace(result is RegisterClassAliasTest);
缺点:为了达到较好的拷贝效果,此方法比较耗时,经过粗略测试,性能应该还能接受。
注意:复杂的显示对象(DisplayObject)无法达到真正的拷贝。
欢迎大家测试使用。
转载地址:http://kejsi.baihongyu.com/