0
votes

I'm having some trouble getting to grips with how a child can refer to the variables of parents.

Here is my Main.as :

package
  {
        import flash.display.MovieClip;

    public class Main extends MovieClip
    {
        public var i;
        public var child: Child;

        public function Main()
        {
            i = 4;
            child = new Child;
        }
    }
}

And here is my Child.as:

package
{
    import flash.display.MovieClip;

    public class Child extends MovieClip
    {
        public function Child()
        {
            trace([parent as MovieClip].i);
        }
    }
}

child is trying to access the public variable i in the parent, but I get the error:

undefined

Using trace(MovieClip(parent).i) instead I get:

TypeError: Error #1009: Cannot access a property or method of a null object reference. at Child() at Main()

I feel like I'm missing something pretty fundamental (like i hasn't been set a value by the time child is constructed) but I can't work out what.

Clarification would be much appreciated.

2

2 Answers

1
votes

The parent property of a DisplayObject gets set when its added to another DisplayObjectContainer via .addChild() or .addChildAt(). These calls are made implicitly by the Flash UI to add children to a visible object.

So there are a few things wrong with what you are doing, some are misunderstandings about how DisplayObjects work in flash, and others are syntactical problems.

When you call new Child(), you are invoking the Child classes' constructor, in your case:

public function Child()
{
    trace([parent as MovieClip].i);
}

At this point, it has not been added as a child to a DisplayObjectContainer. Simply naming it as a child in your parent class does not create this relationship. So in this case, inside your constructor this.parent will alway be null because its just creating a new instance of the Child class, it has no knowledge of any "parent"

There is a pretty big syntax problem here, as well. You are doing as as cast (which will return null if the types are incompatible). In this case, however, parent is already null, but then you are using [], which is the way to write a literal Array. So you are essentially creating a new Array with one element which is null. Then you are attempting to get a property called i on the Array not the parent.

Obviously, this is not what you want to do... At all. You probably meant something like this:

public function Child()
{
    trace((parent as MovieClip).i);
}

But even this isn't right, because i isn't a property on a MovieClip, its a property on your sub-class Main. So you really probably meant:

public function Child()
{
    trace((parent as Main).i);
}

But this will still fail, because like I said before, parent == null because it hasn't been added as a child yet.

Consider the following code:

public class Main extends MovieClip
{
    public var i;
    public var child:Child;

    public function Main()
    {
        i = 4;
        child = new Child();
        child.doWork();
        this.addChild(child)
        child.doWork();
    }
}

And:

public class Child extends MovieClip
{
    public function Child()
    {
        doWork();
    }

    public function doWork()
    {
        if(parent == null) {
            trace("No parent yet.")
            return;
        }

        var mainParent:Main = (parent as Main);
        if(mainParent == null) {
            trace("Parent isn't a instance of Main!")
            return;
        }

        trace(mainParent.i);
    }
}

This should call the method doWork() three times: Once in the child's constructor, then before being added to the display tree, and finally after being added to the display tree. And hopefully it'll make more sense, seeing it work like this.

There is a lot more to learn, especially about events, event bubbling, and how DisplayObjects and DisplayObjectContainers are related/nested. But perhaps this will give you a shove in the correct direction. Just know that parent is just a property of a DisplayObject (one of the ancestors of the MovieClip and many other classes in flash). Understanding how these classes work with each other, and extending them with your own functionality, is key to really understanding flash.

0
votes

Basically parent isn't set until you call the method addChild so:

public class Main extends MovieClip
{
    public var i;
    public var child: Child;

    public function Main()
    {
        i = 4;
        child = new Child;
        addChild(child);
    }
}

of course this means that parent isn't availible and will be undefined in your constructor. I sometimes pass the parent I wish to add the child to into the constructor arguments to simplify adding along with the x/y position if it is appropriate.

public class Child extends MovieClip
{
    public function Child(targetParent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number =  0)
    {
      if (targetParent != null)
     {
        targetParent.addChild(this);
     }

     this.x = xpos;
     this.y = ypos;
    }
}