1
votes

I have trouble with actionScript , im trying to use a simple one line code to access a method inside the Document Class (Main) , but every time i got error . i tried the same code with a movieClip on stage, it work nicely .

Main Class linked to the fla :

package {

import flash.display.*;
import flash.events.*;


public class Main extends MovieClip {


    public function Main() {

        if (stage) {
            init();

        }
        else addEventListener(Event.ADDED_TO_STAGE, init);


    }
    private function init(e:Event = null):void {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        button.addEventListener(MouseEvent.CLICK,_click);

    }
    private function _click(e:MouseEvent):void {
        var l:Leecher = new Leecher();
        l.leech();
    }


    public function callMe():void {
        trace("hey nice work");
    }

}

}

Leecher Class :

package {

    import flash.display.*;

    public class Leecher extends MovieClip {

        public function leech():void
        {
            trace(" leech function ");

            Main(parent).callMe();       // output null object
            Main(root).callMe();        // output null object
            Main(Main).callMe();       // output null object


        }

    }

}

The Same code , but the class linked to a button on stage

package 
{

    import flash.display.*;
    import flash.events.*;


    public class Button extends MovieClip {


        public function Button() {
            this.addEventListener(MouseEvent.CLICK,r_click);
        }
        private function r_click(e:MouseEvent):void {
            var l:Leecher = new Leecher();
            l.leech();
            Main(parent).callMe();  // hey nice work
            Main(root).callMe();    // hey nice work
            Main(Main).callMe();    // output null object

        }
    }

}
1
DisplayObject.parent and DisplayObject.root are defined ONLY when the DisplayObject in question is attached to stage's display list. The Button instance is attached and thus works, the Leecher instance is not attached to anything and its parent and root are both null. Then, Main(anything) is a type casting and class itself is not an instance, so Main(Main) will always give null.Organis

1 Answers

1
votes

The errors are because when that code runs, the Leecher instance has not yet been added to the display list, and as such does not have a parent or root or stage (so parent is null).

Here is a breakdown of what's happening (explained with code comments):

private function _click(e:MouseEvent):void {
    //you instantiate a new Leecher object
    var l:Leecher = new Leecher();

    //you call leech, but this new object does not have a parent because you haven't added it to the display list (via `addChild(l)`)
    l.leech();
}

//your saying parent should be of type Main, then call the callMe method.  However, parent is null because this object is not on the display list
Main(parent).callMe(); 

//same as above, except using root
Main(root).callMe();

//Here you are saying the Main class is of type Main (which since Main is a class and not an instance of Main will error or be null)
Main(Main).callMe();

The root, parent & stage vars of a display object are only populated when said display object is added to to the display list. In the case of root & stage the parent (and any grand parents) must also be added so that the top most parent/grandparent is the stage.

As a result, you need to wait until it's safe to access parent by listening for the Event.ADDED_TO_STAGE event.

private function _click(e:MouseEvent):void {
    var l:Leecher = new Leecher();

    //call the leech method once the child has been added to the stage and has a parent value
    l.addEventListener(Event.ADDED_TO_STAGE, l.leech, false, 0, true);
    addChild(l);
}

If you do the above, you'll need to add an optional event parameter to the leech method or you'll get an error:

public function leech(e:Event = null):void
{

To make your Main class easily accessible, you could use a static reference. Static vars are not tied to an instance of an object, but to the class itself.

public class Main extends MovieClip {
    //create a static var that holds a reference to the root/main instance 
    public static var main:Main;

    public function Main() {
        //assign the static var to this (the instance of Main)
        main = this;

        //...rest of code

If you do that, you can asses your root anywhere in your code by doing Main.main so in your example you could then do:

Main.main.callMe();

I'd recommend reading about static vars more before going crazy using them. Doing what I've just shown for an easy reference to your document class / root is safe, but in other contexts there are some memory & performance nuances it's best to be aware of.