2014-01-06 115 views
0

Flex和ActionScript的新增功能對我來說很裸露。如何在ActionScript中創建對象的未引用副本

我有一個ArrayCollection充滿了自定義對象。我需要能夠創建這個數組的副本,執行一些功能和對數組和對象內的修改。然後,我需要基本上將它重新設置回原始存儲的副本,從我開始之前。

問題(和我發現並正在嘗試解決的錯誤)是我似乎無法創建此數組的副本,它不直接引用原始數組。即:對拷貝的修改也會修改原件。

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> 

而且CustomObject.as

package 
{ 
    public class CustomObject 
    { 
     public var a:String; 
     public var b:String; 
     public var c:String; 

     public function CustomObject() 
     { 
      a = "Hello"; 
      b = "World"; 
      c = "Good-Bye"; 
     } 
    } 
} 

回答

0

經過一些更多的研究後,我得出結論:這裏使用的各種自定義類可能太複雜,無法使用常規實用程序完全複製。它們也用於與我正在修復的特定事件無關的應用程序的各個其他方面,所以我無法真正改變它們以使它們更容易工作。

我結束了循環通過原始arraycollection,使用原來的屬性創建新的對象...即:

 var modified:ArrayCollection = new ArrayCollection(); 
     for each (var myObject:CustomObject in original) 
     { 
      var newObject:CustomObject= new CustomObject(); 
            //... setup properties 
      modified.addItem(newLayer); 
     } 
0

變量對象,基本上是指向該對象的指針。所以,當你這樣做時:

var modified:ArrayCollection = original; 

原始是一個指向ArrayCollection的指針,並且該指針現在也存儲在修改後的變量中。但是,它們仍然指向相同的ArrayCollection。

你說你試過克隆,但暗示它沒有用 - 你沒有詳細說明它爲什麼不起作用。

要複製,您可以在ObjectUtil中使用clonecopy方法。我以爲克隆執行了深層複製,這意味着所有引用的對象也被複制,但複製並不複製引用對象,因此它是「淺」副本。我可能會扭轉局面。

我使用這種方法在一個項目中複製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()); 
} 
+0

我曾與克隆,因爲我在評論中提到的問題出現了,該陣列中的所有對象還原爲基本對象類,並試圖將它們轉換成合適的對象時會拋出一個coersion異常類型。我已經看到並嘗試了您發佈的功能以及相同的結果。 – kweb

+0

我也嘗試循環原始數組和克隆單個對象...即:modified.addItem(clone(originals [i])as CustomObject);這會產生一個空對象數組。 – kweb

+0

您提供可運行樣本嗎? – JeffryHouser

0

如下更改doStuff()函數: - 如果添加[RemoteClass]元數據到您的CustomObject類

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

這會導致與以前相同的問題。該ac被克隆/複製正常,但其中的CustomObject被恢復爲基礎Object。屬性是完整的(與之前一樣),但是嘗試將它們轉換回來會導致null值或異常例外 – kweb

+0

在doStuff方法中添加以下行作爲第一行registerClassAlias(「CustomObjectAlias」,CustomObject);這將允許您的CustomObject類即使在交流克隆/複製後也能保留。然後,您不必將對象投射到CustomObject – Sumit

0

ObjectUtil.clone(original)方法會奏效。

package 
{ 
    [RemoteClass] 
    public class CustomObject 
    { 
     public var a:String; 
     public var b:String; 
     public var c:String; 
    } 
} 

這應該會讓您在迭代克隆的集合時遇到轉換錯誤。請記住,如果您的CustomObject具有其他「自定義」類型的任何屬性,那麼這些類也將需要[RemoteClass]。

+0

我給了這個嘗試,但結束與參數計數不匹配。編寫示例時,我沒有意識到這一點很重要,但是如果向CustomObject的構造函數添加一個String參數,那麼在添加[RemoteClass] – kweb

+0

Ah yes後會以此錯誤結束。我應該提到這一點。正如在你的例子中,[RemoteClass]需要一個無參數的構造函數。 –

+0

...或者你可以給構造函數參數一個默認值。 –

相關問題