如何在不知道AIR for iOS中的确切类型的情况下克隆对象

时间:2012-07-22 09:53:05

标签: actionscript-3 air

我在Flash中编写iOS游戏,我需要一种克隆多态对象的方法。 我有BaseClass,SubClass1,SubClass2(依此类推......)我需要在BaseClass中使用clone()方法,它将创建当前对象的副本,不带条件,例如

var obj:BaseClass;
if(this is SubClass1) { 
   obj = new SubClass1(); 
}else if(this is SubClass2) {
   obj = new SubClass2();
}else...

我需要一种方法来创建一个对象并创建对象的确切字节(是的,浅层副本足以满足我的目的)。我看了看:

AS3 - Clone an object

As3 Copy object

http://actionscripthowto.com/how-to-clone-objects-in-as3/

但似乎都没有用。可能在AIR 3.3 for iOS SDK中不可用。 (他们编译,但代码在我的情况下不起作用)

还有其他任何方式,或者是否有人在AIR for iOS中克隆对象?

谢谢,

可以。

2 个答案:

答案 0 :(得分:1)

使用ActionScript无法进行逐位克隆,除非您的类仅包含原始值(即简单的数据结构)。这与this question's answer中与ByteArray关联的getQualifiedClassName()方法的用途有关 - 但是当您处理复杂类型,特别是显示对象时,您需要处理这些问题。很快就会达到极限(我收集的,你已经意识到了)。

所以这或多或少会让你有两个选择:

  1. 创建一个新对象并复制其所有字段和属性。

    如果您需要行为和字段值,并且您没有使用任何绘图方法(即,您无法以这种方式复制矢量图形),这就是您要采用的方法。在不知道其确切类型的情况下创建新的类实例可以使用反射以通用方式完成,getDefinitionByName()describeType()将帮助您,如果您需要的不仅仅是名称,{{1} }。但是,这也有限制:private字段将不可用(它们不会显示在describeType()提供的信息中),为了避免遇到性能问题,将不得不使用某种缓存。幸运的是,as3commons-reflect已经解决了这个问题,因此实现全功能浅拷贝机制所需的其余部分并不太复杂。

    像这样创建一个新实例:

    var newObject:* = new Type.forInstance( myObject ).clazz();
    

    然后遍历所有访问器,变量和动态属性,并分配旧实例的值。

    我自己实现了一个这样的方法,用于我正在开发的开源框架。您可以在github下载或分叉。目前还没有任何文档,但它的使用就像写作一样简单:

    var myCopy:* = shallowCopy( myObject );
    

    我还有一个copy()方法,可以创建一个真正的深层副本。但是,除了数据结构之外,其他任何东西都没有经过测试(尽管数据结构很大),因此使用风险自负;)

  2. 创建位图副本。

    如果确实有矢量图形,这通常比重新创建图像更容易:只需将对象的内容graphics绘制到新的位图。

    function bitmapCopy( source:Sprite ):Bitmap {
        source.cacheAsBitmap = true;
        var bitmapData:BitmapData = new BitmapData( source.width, source.height, true, 0xFFFFFF );
        bitmapData.draw( source, new Matrix(), null, null, null, true );
    
        return new Bitmap( bitmapData, PixelSnapping.AUTO, true );
    }
    

答案 1 :(得分:0)

您需要在基类中创建一个抽象的clone方法,并为每个子类实现它。在特定实现中,您可以将对象的所有属性复制到新属性。

public class BaseClass {
    public function clone():BaseClass
    {
         // throw an error so you quickly see the places where you forgot to override it
         throw new Error("clone() should be overridden in subclasses!");
         return null;
    }
}

public class Subclass1 extends BaseClass {
    public override function clone():BaseClass
    {
         var copy:Subclass1 = new Subclass1();
         copy.prop1 = prop1;
         copy.prop2 = prop2;
         // .. etc
         return copy;
    }
}

如果您想创建clone的通用默认实现,可以使用describeType访问属性并将其复制:

public function clone():BaseClass
{
    var defn:XML = describeType(this);
    var clsName:String = defn.@name;
    var cls:Class = getDefinitionByName(clsName) as Class;
    var inst:* = new cls();
    for each(var prop:String in (defn.variable + defn.accessor.(@access == 'readwrite')).@name )
    {
        inst[prop] = this[prop];
    }
    return inst;
}

这个问题的主要问题是describeType XML会变得非常大 - 特别是在处理扩展DisplayObject的对象时。这可能会占用大量内存并且在iOS上速度很慢。