zoukankan      html  css  js  c++  java
  • AS3隐藏特性——深拷贝数据对象

    以前在《ActionScript殿堂之路》上就看到过的“深拷贝”概念一直没有好好地在实战中用到过,但是最近在开发过程中,我发现我在编写VO数据对象时的一个老习惯很浪费我的编码时间,这个习惯是这样的,我要为一个VO对象写一个clone复制方法来产生一个该对象的副本,我习惯的做法如下:

    package 
    { 
    	import flash.net.registerClassAlias;
    	import flash.utils.ByteArray;
    	import flash.utils.getDefinitionByName;
    	import flash.utils.getQualifiedClassName;
    
    	public class MyVO 
    	{ 
    		public var id:String;
    		
    		public var name:String;
    		
    		public function MyVO()
    		{
    		} 
    		
    		public function clone():MyVO
    		{
    			var vo:MyVO = new MyVO();
    			vo.id = this.id;
    			vo.name = this.name;
    			
    			return vo;
    		}
    	} 
    } 
    

    在这个clone方法中我要做的事情很多,就是机械式地把我该VO类中全部声明的属性都逐个地赋值给新的一个VO类,这样做非常浪费代码量,而且每新增一个属性还需要同时修改clone方法,如我新增一个属性叫sex,就必须添加如下代码:

    public class MyVO  
    {  	
    	public var sex:int;  
    	...... 		 	
    	public function clone():MyVO 	
    	{ 		
    		.........
    		vo.sex = this.sex;
     		return vo; 	
    	} 
    }  
    
    

    而且如此做,在使用“继承”时非常不便,比如我创建一个MyVO2,它继承了MyVO,那么它自然也继承了MyVO的clone方法,不过我们发现其在调用clone方法后返回的结果为MyVO对象,而非MyVO2对象,此时还必须重载clone方法来让返回类型正确:

    public class MyVO2  
    {  	
    	public var Number;  
    			 	
    	override public function clone():MyVO 	
    	{ 		
    		var vo:MyVO2 = new MyVO2();//类型改成MyVO2
    		vo.id = this.id;
    		vo.name = this.name;
    		vo.sex = this.sex;
    		vo.width = this.width;
     		return vo; 	
    	} 
    }
    
    

    于是我就想到了使用深拷贝试试看行不行,就重构了一下我的clone方法:

    /**
    * 完全克隆此对象
    * @return 
    * 
    */		
    public function clone():MyVO
    {
    	var copier:ByteArray	= new ByteArray();
    	copier.writeObject(this);
    	copier.position		= 0;
    			
    	return copier.readObject() as MyVO;
    }
    
    

    但是这么写了之后,我调用clone方法发现返回结果为null,这究竟是怎么回事?what the hell is going on?经调试后发现,调用copier这个ByteArray对象的readObject方法后返回的是一个Object类型的对象,而非MyVO这个我要拷贝的类型。

    如何才能让其深拷贝得到的对象类型符合要求呢?我找到了flash.net.registerClassAlias这个方法,貌似可行,先看看AS3语言参考手册中对其的描述:

    ------------------------------------------------------------------------------------------------------------------------------------

     

    registerClassAlias

    () 函数  

     

    public function registerClassAlias(aliasName:String, classObject:Class):void

     

    语言版本: ActionScript 3.0
    运行时版本: AIR 1.0 Flash Player 9

     

    当以 Action Message Format (AMF) 对一个对象进行编码时,保留该对象的类(类型)。将对象编码为 AMF  时,该函数将保存该对象的类的别名,以便在解码对象时可以恢复该类。如果编码上下文没有为对象的类注册别名,该对象将被编码为一个匿名对象。同样,如果解码上下文注册了不同的别名,将为解码后的数据创建一个匿名对象。

    LocalConnection、ByteArray、SharedObject、NetConnection 及 NetStream 均为将对象编码为 AMF  的类的示例。

    编码和解码上下文不必对别名使用相同的类。它们可以主动地改变类,条件是目标类包含源类序列化的所有成员。

     

    参数

      aliasName:String — 要使用的别名。
     
      classObject:Class — 与给定别名相关联的类。

     


     
    示例  

    此示例使用 registerClassAlias() 函数为 ExampleClass  注册一个别名 ( com.example.eg )。由于为类注册了别名,因此可以将对象作为 ExampleClass  的实例反序列化,且代码将输出 true。如果删除 registerClassAlias()  调用,则代码将输出 false
    package {
        import flash.display.Sprite;
        import flash.net.registerClassAlias;
        import flash.utils.ByteArray;
    
        public class RegisterClassAliasExample extends Sprite {
            public function RegisterClassAliasExample() {
                registerClassAlias("com.example.eg", ExampleClass);
                var eg1:ExampleClass = new ExampleClass();
                var ba:ByteArray = new ByteArray();
                ba.writeObject(eg1);
                ba.position = 0;
                var eg2:* = ba.readObject();
                trace(eg2 is ExampleClass); // true
            }
        }
    }
    
    class ExampleClass {}
    
    ------------------------------------------------------------------------------------------------------------------------------------
    看起来不错哦,让我们接下来试试看:
    public function clone():Object
    {
    	var typeName:String		= getQualifiedClassName(this);//获取当前类完全类名
    	var packageName:String	= typeName.split("::")[0];//截取命名空间之前的包名
    	var type:Class			= getDefinitionByName(typeName) as Class;//获取当前类定义
    	
    	registerClassAlias(packageName, type);//使用当前类的包名作为类别名,类定义作为注册类
    	
    	var copier:ByteArray	= new ByteArray();
    	copier.writeObject(this);
    	copier.position			= 0;
    	
    	return copier.readObject();
    }
    

    registerClassAlias的第一个参数为要使用的别名,我觉得这个别名随便取什么都不会有影响,不过为了规范起见,还是将别名设置为当前类的包名好了。此时调用clone方法发现能够如预期那样得到正确类型的对象,且保留了和拷贝源一致的所有属性,耶!拷贝成功!而且使用这招可以在使用继承的时候不必写任何冗余代码,即MyVO的任何子类都不需要重写clone方法也能正常工作。

    知道此方法的人撸过就好了,不知道的人记一下哦,省得和我以前一样,加重编码负担。不过需要注意哦,深拷贝对显示对象(DisplayObject)不起作用~

  • 相关阅读:
    个人管理:提高你的搜商
    敏捷个人:提供更多文档下载,并转载一篇敏捷个人读书笔记
    个人管理: 激励你的一句话
    敏捷个人 从Scrum实践来思考如何导入价值观
    信息系统开发平台OpenExpressApp 如何解决ComboBox.TextProperty绑定带来问题的来龙去脉
    敏捷个人 敏捷个人价值观,欢迎提出你的意见和你的价值观
    使用VS2010的CodedUI来做自己的自动化测试框架
    .Net4下的MEF(Managed Extensibility Framework) 架构简介
    IronRuby - 快速在半小时学习Ruby基础知识
    敏捷个人 项目网站文档页签增加blog链接
  • 原文地址:https://www.cnblogs.com/chenhongyu/p/3477246.html
Copyright © 2011-2022 走看看