flashactionscript-3cs4

MovieClips don't keep their base class if childed to a movieclip that's added dynamically


I have a holder movieclip, its base class is foo.

package {
    import flash.display.MovieClip;

    public class Foo extends MovieClip {
        public function Foo() {
            trace("foo");
        }
    }
}

Within foo are a number of other movieclips, with a base class of bar.

package {
    import flash.display.MovieClip;

    public class Bar extends MovieClip {
        public function Bar() {
            trace("bar");
        }
    }
}

I put a trace in the constructor of bar so I can tell if it's being loaded properly, and when I drag out foo onto the scene and run the clip, all the little bars within it fire off correctly. However, when I add it to the scene dynamically, such as like this in the Main class:

package {
    import flash.display.MovieClip;

    public class Main extends MovieClip {
        public function Main() {
            this.addChild(new Foo());
        }
    }
}

Suddenly, all the little bar movieclips within foo revert to regular old movieclips and don't fire. What's interesting is if you typecast one them as Bar at some point, and their normal class is set to Bar (within the movieclip itself, rather than base class), it works and the constructors all fire, like this:

    public function Main() {
        var foo:Foo = new Foo();
        stage.addChild(foo);
        foo.x = 0;
        foo.y = 0;

        trace(foo.getChildAt(1) as Bar);
    }//Main()

However, if you want multiple different types of Bar clips, and give each a base class of Bar, this won't work. They all spawn as generic movieclips. It DOES work if you go through and typecast them as either Bar1 or Bar2, but that means in practice you would have to try to typecast every child as every top-level object type every time you added the clip to the stage.

You also can't have a bunch of movieclips of the same type since Flash doesn't allow it, so each one needs to be a new class, and have that class typecasted when the parent is placed on stage. Kind of defeats the purpose of OOP.

This seems to be a bug in Flash itself, but is there any way to fix it?


Solution

  • The problem lies in your declaration of Foo's class members. If you want Flash to instantiate the elements as anything else than a MovieClip or Sprite, you must properly add a member declaration to the class, or declare the type when you use the new keyword.

    This works:

    package {
    import flash.display.MovieClip;
    import flash.utils.describeType;
    
    public class Foo extends MovieClip {
        public var bar1:Bar1;
        public var bar2:Bar2;
        public var bar3:Bar1;
        public var bar4:Bar2;
    
        public function Foo() {
            trace("foo", this.numChildren);
    
        }
    }
    }
    

    You can also just set the ActionScript preferences to "Automatically declare stage instances" and omit the class declaration, if your class doesn't really do anything special.

    ActionScript is quite tolerant with types, but it seems the compiler ignores the types declared in the panel until it finds some kind of reference in the code, probably to prevent accidental bloating of the binary if someone forgot to erase a class name somewhere in the library.