1
votes

The Code bellow is a simplified version of what I am trying to do. My actual code involves copying an item from one array to another (which I am able to do). Then displaying the contents of both arrays on the stage.

//blueCircle is a library object with proper linkage set up.
var ball = new blueCircle();
ball.x=100;
ball.y=100;
addChild(ball);

//This is the line that is giving me trouble.
var anotherBall= ball;
anotherBall.x=200;
anotherBall.y=200;
addChild(anotherBall);

When I run this code only 1 ball appears on the stage at (200,200).

Is there another way to assign one value to another so that it will be duplicated rather then just adding a pointer to the original variable? if not is there a way to copy the instance of ball and add it to them memory location of another ball?

I know that I could call:

var anotherBall= new blueCircle(); 

but this won't work for the application I am writing because the contents of the array I am trying to copy from are all different types of objects.

4
If you want 2 ball objects then you need to use the "new" operator 2 times. Anything else is just passing the memory reference around to other variables like in your example.The_asMan

4 Answers

3
votes

The error with your code has to do with a distinction in programming of assigning data by reference or by value. In ActionScript 3, every variable is a pointer, and they only store references to the object. In addition, the assignment operator for non-primitive types only copies a reference (called a shallow copy).

var x:int = 0;
var y:int = x;
y += 1;

trace(x, y); // Output is "0 1" because int is a primitive datatype.

var objectA:Object = { name: "I'm object A." };
var objectB:Object = objectA; // This is just a shallow copy. objectA and objectB 
                              // point to the same value.

objectB.name = "I'm object B.";

trace(objectA.name, objectB.name); // Output is "I'm object B. I'm object B."

ActionScript 3 doesn't have a great way around this syntax-wise, so the solution usually lies in the structure of your program. Maybe your BlueCircle class has a clone method?

 public class BlueCircle extends MovieClip
 {
     public var someKindOfData:String;

     public function BlueCircle()
     {
         someKindOfData = "something";
     }

     public function clone():BlueCircle
     {
         var clone:BlueCircle = new BlueCircle();

         clone.x = x;
         clone.y = y;
         clone.someKindOfData = someKindOfData;

         return clone;
     }
 }

Alternatively, there is a (kind of messy) way to make a deep copy of a MovieClip, which is detailed here.

0
votes

In ActionScript you cant copy objects at all. All objects assigns by reference, except int, uint, Number, String, Boolean. There is no way to copy Sprite. You only can create new sprite. Sprite may have only one parent, and if you try to add it to another DisplayObjectContainer its automatically removes from old parent. Because Sprite extends EventDispatcher, you hasn't access to its listeners, and there is no way to access it.

0
votes

You can create a new instance of the object in the following way:

Main.as(document class):

package 
{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.utils.getDefinitionByName;
    import flash.utils.getQualifiedClassName;
    import Circle;
    import Square;

    public class Main extends Sprite 
    {

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            var shapes:Vector.<Shape> = Vector.<Shape>([new Circle(), 
                                                        new Square()]);

            var shape:Shape = shapes[0];
            addChild(shape);

            var shapeClone:Shape = cloneShape(shape);
            shapeClone.x = 200;
            addChild(shapeClone);

        }// end function

        private function cloneShape(shape:Shape):Shape
        {
            var ShapeClass:Class = getClass(shape);

            return new ShapeClass();

        }// end function

        private function getClass(object:Object):Class
        {
            return getDefinitionByName(getQualifiedClassName(object)) as Class;

        }// end function

    }// end class

}// end package

Circle.as:

package  
{
    import flash.display.Shape;

    public class Circle extends Shape
    {
        public function Circle()
        {
            graphics.lineStyle(1);
            graphics.drawCircle(50, 50, 50);
            graphics.endFill();

        }// end function

    }// end class

}// end package

Square.as:

package
{
    import flash.display.Shape;

    public class Square extends Shape
    {
        public function Square()
        {
            graphics.lineStyle(1);
            graphics.drawRect(0,0,100, 100);
            graphics.endFill();

        }// end function

    }// end class

}// end package
0
votes
"but this won't work for the application I am writing because the contents of 
the array I am trying to copy from are all different types of objects..."

If your main issue is not knowing what the copied Object class should be , you could do something like this:

 // an example of the object you would like to copy.
 // assuming that you don't know what the class is...
 var mc:MovieClip = new MovieClip();

 // getQualifiedClassName will return the name of the object class
 // as a String, if the object was a blueCircle, the String returned
 // would then be "blueCircle", in this instance it will return
 // flash.display::MovieClip
 var className:String = getQualifiedClassName(mc );

 // now that you have the name you can get the Class
 // with the getDefinitionByName method
 var objectClass:Object = getDefinitionByName( className );

 // time to copy your object
 var obj:Object = new objectClass();

 // check it all here...
 trace("the class name is ", className );
 trace("the object is ", objectClass );
 trace("the copy is ", obj );

You could actually create a static function in a "utility" class that would return a copy of any object you pass as a parameter

    //Let's say you have a MyUtils Class
    public static function getObjectCopy( obj:* ):*
    {
         var className:String = getQualifiedClassName(obj ); 
         var objClass:Object = getDefinitionByName( className );

         return new objClass();
    }

    //Then you could do
    var ball = new blueCircle();
    ball.x=100;
    ball.y=100;
    addChild(ball);

    //And as explained above , you don't need to know the object type
    var anotherBall= MyUtils.getObjectCopy( ball );
    anotherBall.x=200;
    anotherBall.y=200;
    addChild(anotherBall);