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

Actionscript 3 如何在不知道iOS在空中的确切类型的情况下克隆对象,actionscript-3,air,Actionscript 3,Air,我正在用Flash编写一个iOS游戏,我需要一种克隆多态对象的方法。 我有基类、子类1、子类2(等等),我需要基类中的clone()方法,该方法将创建当前对象的副本,,而不带条件,例如 var obj:BaseClass; if(this is SubClass1) { obj = new SubClass1(); }else if(this is SubClass2) { obj = new SubClass2(); }else... 我需要一种方法来创建一个对象并创建对象的

我正在用Flash编写一个iOS游戏,我需要一种克隆多态对象的方法。 我有基类、子类1、子类2(等等),我需要基类中的clone()方法,该方法将创建当前对象的副本,,而不带条件,例如

var obj:BaseClass;
if(this is SubClass1) { 
   obj = new SubClass1(); 
}else if(this is SubClass2) {
   obj = new SubClass2();
}else...
我需要一种方法来创建一个对象并创建对象的精确字节(是的,一个浅拷贝就足够了)。我看过:

但似乎都不管用。对于iOS SDK,AIR 3.3可能不可用。(它们可以编译,但代码在我的情况下不起作用)

有没有其他方法,或者有没有人在iOS上实现了在空中克隆一个对象

谢谢


Can.

您需要在基类中创建一个抽象的
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;
}

这方面的主要问题是DescripteType XML可能会变得相当大,尤其是在处理扩展了
DisplayObject
的对象时。这可能会占用大量内存,并且在iOS上速度较慢。

不能使用ActionScript进行逐位克隆,除非您的类只包含基本值(即简单的数据结构)。这就是您在中链接到的
ByteArray
方法的用途-但是当您处理复杂类型,尤其是显示对象时,您很快就会达到极限(据我所知,您已经意识到)

因此,这或多或少给您留下了两个选择:

  • 创建新对象并复制其所有字段和属性

    如果您需要行为和字段值,并且没有使用任何绘图方法(即,您不能以这种方式复制矢量图形),则可以使用此方法。创建一个新的类实例而不知道它的确切类型可以通过使用反射以一种通用的方式完成,
    getQualifiedClassName()
    getDefinitionByName()
    将在这方面帮助您,如果您需要的不仅仅是名称,
    describeType()
    。不过,这也有限制:
    private
    字段将不可用(它们不会出现在
    describeType()
    提供的信息中),并且为了不出现性能问题,您必须使用某种缓存。幸运的是,我们已经解决了这个问题,所以实现一个功能齐全的浅层复制机制所需的其余部分并不太复杂

    创建一个新实例,如下所示:

    var newObject:* = new Type.forInstance( myObject ).clazz();
    
    然后迭代所有访问器、变量和动态属性,并分配旧实例的值

    我自己也实现了这样一种方法,用于我正在开发的开源框架。您可以下载或在。目前还没有任何文档,但它的使用非常简单:

    var myCopy:* = shallowCopy( myObject );
    
    我还有一个
    copy()
    方法,它创建了一个真正的深度副本。但是,除了数据结构(尽管是大型结构)之外,还没有对其进行测试,因此使用风险自负;)

  • 创建位图副本

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

    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 );
    }
    

  • 有几种方法可以做到这一点,但首先请解释为什么需要将其限制在基类中-似乎最明显的选择是为每个子类型重写clone()方法,并手动复制所有字段。我不需要在子类中做任何额外的事,因为子类中会有很多字段。因此,复制位的clone()方法就足够了。如果我需要在任何子类的clone方法中添加任何内容,我只需要重写它并添加行为。不,这显然不是我想要的。我需要一个通用的默认实现,它将通过查看对象的当前类型在内存中实际创建对象。(无条件)如var newobj:BaseClass=createBitByBitExactCopy(derivedClassInstance);我不知道派生实例的确切类型。我只知道它是基类的一个派生类。你们不能访问内存中的对象。如果您想创建一个通用克隆,可以执行类似于我在编辑中添加的操作。否则,您可以使用
    ByteArray.writeObject()
    ,但您仍然需要做一些额外的工作,而且它不会复制内存。ByteArray.writeObject实际上正是我想要的,但我似乎无法让它在AIR 3.3 for iOS上运行。我很高兴使用(并测试)您的库。但是这个项目将商业化(我计划在App Store中以一两美元的价格出售这个游戏),在我的项目中使用你的库会导致许可证问题吗?不会。这是一个非常早期的阶段,我还没有添加任何许可证信息,但它将在麻省理工学院的许可证下。我希望你能给我一点荣誉感,但这当然不是要求。我用过你的图书馆。它非常容易使用,并且能够创建相同类型的新对象。但是,它没有将任何属性从旧对象复制到新对象。它只是创建了一个相同类型的新实例(我一开始就试图实现),但没有一个字段被复制到新对象中。我真的不知道如何将某些内容放到github中,但这里是我仅有的代码:StandardSmileys从中派生(目前没有添加任何内容)(作为带有AS3导出选项的Flash中设计的MovieClip),我使用的代码是copySmiley函数(smi:Smiley):Smiley{var newsmi:Smiley=shallowCopy(smi);return newsmi;}好的,我看到您没有使用AS3的访问器约定-
    getField()
    setField()
    将无法识别