2014-01-06 4 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.

Вы сказали, что попробовали клонировать, но ссылались на то, что это не сработало - вы не уточнили, почему это не сработало.

Для копирования вы можете использовать метод clone или copy в 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()); 
} 
+0

Проблема, которую я имел с клоном, как я уже говорил в комментариях было то, что все объекты в массиве вернулись к классу базового объекта и будут бросать исключение приводки при попытке приведения их к соответствующему объекту тип. Я видел и пробовал функцию, которую вы опубликовали, с тем же результатом. – kweb

+0

Я также пробовал перебирать исходный массив и клонировать отдельные объекты ... ie: modified.addItem (клон (оригиналы [i]) как CustomObject); Это приводит к массиву нулевых объектов. – kweb

+0

КАК вы предоставляете исполняемый образец? – JeffryHouser

0

Изменение функции 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); 
      } 
     } 
+0

Это приводит к той же проблеме, что и раньше. AC клонирован/скопирован в порядке, однако CustomObject внутри него возвращается обратно к базовому объекту. Свойства остаются неповрежденными (как и раньше), однако попытка вернуть результаты обратно либо в нулевые значения, либо в исключениях для обработки. – kweb

+0

Добавьте следующую строку в свой метод doStuff в качестве первой строки registerClassAlias ​​(«CustomObjectAlias», CustomObject); Это позволит сохранить ваш класс CustomObject даже после клона/копии ac. Тогда вам не нужно бросать объект в CustomObject – Sumit

0

ObjectUtil.clone(original) подход будет работать, если вы добавите [RemoteClass] Метаданные для вашего CustomObject класса.

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

Это должно помешать вам прибегнуть к ошибкам при литье при повторении клонированной коллекции. Имейте в виду, если ваш CustomObject имеет какие-либо свойства других типов «Custom», для этих классов также потребуется [RemoteClass].

+0

. Я дал это попробовать, однако в итоге оказалось несоответствие счетчика аргументов. Я не понимал, что это важно при написании примера, но если вы добавите аргумент String в конструктор для CustomObject, он заканчивается этой ошибкой после добавления [RemoteClass] – kweb

+0

Ах да. Я должен был упомянуть об этом. Как и в вашем примере, с [RemoteClass] требуется конструктор без параметров. –

+0

... или вы можете дать аргументу конструктора значение по умолчанию. –

Смежные вопросы