汎用性の高いディープコピーを考える
/**
* Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/5fQr
*/
//sample of deep copy
//Adobeのlivedocsに載っていた方法でのディープコピーがうまく機能しなかったので、
//汎用性の高いディープコピー(深いコピー)を考える。
//下のコードで,次のようなインスタンスのディープコピーを実現できる。
//deep copy
// Object,Array,Vectorクラスのインスタンス
// clone関数で自分自身の複製を返すインスタンス(例: Event,Matrix,Point,BitmapDataなど)
// Object,Array,Vectorや、clone関数で自分自身の複製を返すインスタンスを含むObject,Array,Vector
// ただし、
// プリミティブ型,Object,Array,Vectorクラス以外のインスタンスはシャローコピーになる。
// 自分自身の複製を返さないclone関数があると正しく動作しない。
package {
import flash.utils.ByteArray;
import flash.geom.Matrix;
import flash.display.Sprite;
import com.bit101.components.TextArea;
import flash.utils.getQualifiedClassName;
public class FlashTest extends Sprite {
public function FlashTest() {
// write as3 code here..
var ba:ByteArray = new ByteArray();
ba.writeDouble(1232134.413);
var objA:Object = {
a:1,
b:2,
c:3,
arr:[1,2,3],
o:{
a:1,
str:"xyz",
m: new Matrix(0,0,1,0),
ba: ba,
vec:Vector.<String>( [null,null,null] )
},
f:function f():void{ trace("ok?") } // functionはディープコピーにならない
};
var objB:Object = objA; //比較用 shallow copy
var objC:Object = clone( objA ); //deep copy1
objA.o.vec[0] = "objA";
objB.o.vec[1] = "objB";
objC.o.vec[2] = "objC";
var text:TextArea = new TextArea( this );
text.setSize( 465, 465 );
text.text = "\nobjA:" + string(objA) +
"\n\nobjB(shallow copy):" + string(objB) +
"\n\nobjC(deep copy):" + string(objC);
}
}
}
//ディープコピーを行う関数1 (deep copy1)
import flash.utils.getQualifiedClassName;
import flash.utils.getDefinitionByName;
import flash.utils.ByteArray;
function clone(arg:*):*{
var name:String = getQualifiedClassName(arg);
var cl:*;
if( name == "Object" || name == "Array" || arg is Vector.<*> || name == "flash.utils::Dictionary" ){
var classDef:Class = getDefinitionByName(name) as Class;
cl = new classDef();
var flag:Boolean = false;
for( var s:Object in arg ){
cl[s] = clone( arg[s] );
flag = true;
}
return cl
}else if( name == "flash.utils::ByteArray" ){
cl = new ByteArray()
cl.readBytes(arg);
cl.position = 0;
return cl;
}else if( arg is Object && arg.hasOwnProperty("clone") && arg.clone is Function ){
return arg.clone();
}
return arg;
}
function string(arg:*, index:String = ""):String{
var str:String = "";
var name:String = getQualifiedClassName(arg);
if( name == "Object" ){
for( var s:String in arg){str+="\n "+ index + s + " : " + string(arg[s],index+" " )}
return "{ " + arg.toString() + str + "\n" + index + "}";
}
return arg;
}