Apache flex 如何在ActionScript中创建对象的未引用副本
我有一个充满自定义对象的ArrayCollection。我需要能够创建这个数组的副本,对数组和其中的对象执行一些功能和修改。然后,我需要基本上将其重置为开始之前存储的原始副本 问题(以及我发现并试图修复的bug)是,我似乎无法创建一个不直接引用原始数组的数组副本。ie:对副本的修改也将修改原件Apache flex 如何在ActionScript中创建对象的未引用副本,apache-flex,object,actionscript,reference,Apache Flex,Object,Actionscript,Reference,我有一个充满自定义对象的ArrayCollection。我需要能够创建这个数组的副本,对数组和其中的对象执行一些功能和修改。然后,我需要基本上将其重置为开始之前存储的原始副本 问题(以及我发现并试图修复的bug)是,我似乎无法创建一个不直接引用原始数组的数组副本。ie:对副本的修改也将修改原件 private var original:ArrayCollection = new ArrayCollection(); ... private function doStuff() { va
private var original:ArrayCollection = new ArrayCollection();
...
private function doStuff()
{
var modified:ArrayCollection = original;
for each (var myObj:CustomObject in modified)
...
}
我最接近的方法是使用ObjectUtil.clone
private var original:ArrayCollection = new ArrayCollection();
...
private function doStuff()
{
var modified:ArrayCollection = ObjectUtil.clone(original);
for each (var myObj:CustomObject in modified)
{
//Error here as the clone worked, however the objects in the array reverted to the base Object Class and couldn't be cast back to their actual CustomObject type
}
}
下面是一个工作示例:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.events.FlexEvent;
private var originals:ArrayCollection;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
originals = new ArrayCollection();
for (var i:int = 0; i <= 5; i++)
{
var myObj:CustomObject = new CustomObject();
originals.addItem(myObj);
}
doStuff();
}
private function doStuff():void
{
var modified:ArrayCollection = clone(originals);
for (var i:int = 0; i < modified.length; i++)
{
var myDupObj:CustomObject = modified[i] as CustomObject;
//do stuff
trace(myDupObj);
}
}
private function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Application>
对象的变量,基本上是指向该对象的指针。因此,当您这样做时:
var modified:ArrayCollection = original;
Original是指向ArrayCollection的指针,该指针现在也存储在修改后的变量中。但是,它们仍然指向同一个ArrayCollection
你说你试过克隆,但暗示它不起作用——你没有详细说明为什么它不起作用
要复制,可以使用ObjectUtil中的或方法。我认为克隆执行了深度复制,这意味着所有被引用的对象也被复制,但复制并没有复制被引用的对象,所以它是一个“浅”复制。我可能会反过来
我使用此方法在一个项目中复制ArrayCollection;我相信这是ObjectUtil.clone的一个修改版本
// clone method in ObjectUtils needs a UID; this one doesn't
public static function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
更改doStuff()函数,如下所示:-
private function doStuff():void
{
var modified:ArrayCollection = new ArrayCollection()
modified.addAll(ObjectUtil.copy(originals.list) as IList);
//following code only for testing
for (var i:int = 0; i < modified.length; i++)
{
modified[i].a = "Bye";
trace(modified[i].a);
trace(originals[i].a);
}
}
私有函数doStuff():void
{
var modified:ArrayCollection=新的ArrayCollection()
modified.addAll(ObjectUtil.copy(originals.list)作为IList);
//以下代码仅用于测试
对于(变量i:int=0;i
如果将[RemoteClass]元数据添加到CustomObject类中,则ObjectUtil.clone(原始)
方法将起作用
package
{
[RemoteClass]
public class CustomObject
{
public var a:String;
public var b:String;
public var c:String;
}
}
这将防止您在迭代克隆的集合时遇到强制转换错误。请记住,如果您的CustomObject具有其他“自定义”类型的任何属性,则这些类也需要[RemoteClass]。经过进一步研究,我得出结论,此处使用的各种自定义类可能太复杂,无法使用通用工具完全复制。它们还用于与我试图修复的特定事物无关的应用程序的各个其他方面,因此我无法真正更改它们以使其工作更轻松 我最终在原始arraycollection中循环,使用原始arraycollection中的属性创建新对象。。。即:
var modified:ArrayCollection = new ArrayCollection();
for each (var myObject:CustomObject in original)
{
var newObject:CustomObject= new CustomObject();
//... setup properties
modified.addItem(newLayer);
}
正如我在评论中提到的那样,克隆的问题是数组中的所有对象都恢复为基本对象类,并且在尝试将它们转换为正确的对象类型时会引发协同异常。我已经看过并尝试过你发布的函数,结果也是一样的。我还尝试过在原始数组中循环并克隆单个对象。。。ie:modified.addItem(克隆(原件[i])作为CustomObject);这将导致一个空对象数组。您能提供一个可运行的示例吗?发布在上面编辑的问题中。调试时您会注意到,原始ac将充满CustomObject,而修改后的ac将只是Object。当我在修改的ac中循环时,我在那里的强制转换导致myDupObj变为null。这导致了与以前相同的问题。ac克隆/复制正常,但其中的CustomObject恢复为基本对象。属性是完整的(如前所述),但是尝试将其强制转换会导致空值或协同异常在doStuff方法中添加以下行作为第一行registerClassAlias(“CustomObjectAlias”,CustomObject);这将允许您的CustomObject类即使在ac克隆/复制之后也被保留。然后您不必将对象强制转换为CustomObjectI,我尝试了一下,但最终导致参数计数不匹配。在编写示例时,我没有意识到这一点很重要,但是如果在CustomObject的构造函数中添加一个字符串参数,那么在添加[RemoteClass]之后就会出现此错误。啊,是的。我应该提到这一点。在您的示例中,[RemoteClass]……需要一个无参数构造函数,或者您可以给构造函数参数一个默认值。
var modified:ArrayCollection = new ArrayCollection();
for each (var myObject:CustomObject in original)
{
var newObject:CustomObject= new CustomObject();
//... setup properties
modified.addItem(newLayer);
}