ActionScript.org Flash, Flex and ActionScript Resources - http://www.actionscript.org/resources
AS3 Classes Using Inheritance
http://www.actionscript.org/resources/articles/716/1/AS3-Classes-Using-Inheritance/Page1.html
Jody Hall
My interest in Flash started mostly because of a Jib-Jab cartoon ("This Land") in 2004. I'm the author of a feature I call "Mazoons," which are a combination of mazes and cartoons. In 2002, I even had a book published, "Super Silly Mazes." I'm not a professional programmer, but making my mazes interactive by programming them with Flash has become a hobby/obsession of mine in recent years. My efforts so far can be seen at http://www.mazoons.com/Flash_mazes.htm.  
By Jody Hall
Published on December 27, 2007
 
In this tutorial, I explain the difference between using "composition" vs. using "inheritance." My previous two tutorials both used composition. In this tutorial, you'll learn the other technique, inheritance. You'll learn how to associate a MovieClip or other symbol in the library with a custom class file, so that the symbol is the class and vice versa. I'll also cover the difference between designating the Class as opposed to designating the Base Class in the "Linkage Properties" dialog box, and what it's used for.

Introduction: Inheritance vs. Composition
In my previous two tutorials, I had you create some custom classes that controlled MovieClips that were stage instances. These stage instances were given instance names in the fla, and the instance name was sent to the class as an argument.

You might have wondered why I would have you create a class that has a MovieClip as a property, instead of just creating a class that is a MovieClip. The first technique is called "composition" and the second "inheritance." This is not to imply that this only applies to MovieClips, it's just that MovieClips make a great, easy to understand example of it. So, the difference between composition and inheritance (in the case of MovieClips) is the difference between whether an object HAS A MovieClip as a property, or whether the object IS A MovieClip. So the former two tutorials were both examples of the first technique, composition, even though I didn't tell you that at the time.

I did it this way for several reasons: First, I knew that a lot of people would already be familiar with drawing something on the stage, converting it to a symbol, and giving it an instance name. That being the case, I could take you from what you already knew, and then go into how to use a class to control that instance. Secondly, I wanted you to realize that although a MovieClip is an object, certainly not all objects are MovieClips. An object is basically a custom datatype, and can be composed of anything you want, even instances of other classes. So, it was to get you to start thinking in terms of objects, but not to confuse objects with MovieClips. And the final reason: composition is a valid technique, and it allowed me to demonstrate at the end of the first tutorial that you could control the same MovieClip instance using two different classes.

I'd also like to clarify something here. I don't have an OOP background, don't know design patterns or anything (yet, haha!), and am really just getting started with classes myself. I had just begun to get into using classes in AS2, just before AS3 came out. I don't do flash development for a living, rather it's a hobby of mine at the moment. However, since I'm basically a beginner with OOP and AS3 myself, and I've had to dig to find out a lot of things, I feel that rather than disqualifying me, this actually helps me to better relate these things to other beginners. While I can't bring you past whatever level I'm at, what I can do is explain the things that I've learned in terms you can understand, because I've experienced it too, and not all that long ago. Sound good? Read on.

The next page will explain how to use the other technique, inheritance, to link a MovieClip in the library to a class file.

Inheritance: Linking a Library MovieClip to a Custom Class
Here's an example of using inheritance instead of composition. This is just going to be a re-creation of ClipDragger from the first tutorial. Since you'll save it to the same package as before, and just to give it a new name, I'll call this class ClipDragger2. So, inside of flash, choose File, New, then Actionscript File. Inside the script pane, enter the following:
[as]package com.mysite.mouse {
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
   
    public class ClipDragger2 extends MovieClip {
        public function ClipDragger2() {
            buttonMode = true;
            addEventListener(MouseEvent.MOUSE_DOWN, drag);
            stage.addEventListener(MouseEvent.MOUSE_UP, drop);
        }
        private function drag(event:MouseEvent) {
            parent.setChildIndex(this, this.parent.numChildren - 1);
            startDrag();
        }
        private function drop(event:MouseEvent) {
            stopDrag();
        }
    }
}[/as]
Save the file. Choose File, Save. If you followed the first two tutorials, you know what's coming next: navigate to the folder you designated in your classpath, then to com, then mysite, then mouse. Save the file there as ClipDragger2.

The first thing to notice about ClipDragger2 is that it extends MovieClip. This means that the class we're defining here IS a MovieClip. Remember, this is the difference between inheritance and composition. Since this class is a MovieClip, all instances of this class will be MovieClips, and will automatically have all the properties and methods that MovieClips have. This makes a difference in the way you compose the class itself. Notice that in the constructor, I can say:
[as]buttonMode = true;
addEventListener(MouseEvent.MOUSE_DOWN, drag);
stage.addEventListener(MouseEvent.MOUSE_UP, drop);[/as]
Since this class represents a MovieClip directly, any instance of this class IS a MovieClip, so the above first line is saying, "Hey, I'm a MovieClip instance. That's understood. So, set my buttonMode property to true, will ya?" Same thing with the next line, which is like saying, "Add an event listener to me." Same thing with the last line, which is like saying "Hey, add an event listener to my stage property." In every case, it's not necessary to preface the property or method with anything, because those are all properties and methods that MovieClips have, and our class IS a MovieClip (can't emphasize enough, haha).

The same could be said for every reference throughout the class. When "parent" is used, it means "my parent." When startDrag is used, it means "start dragging me." When stopDrag is used "stop dragging me." If you did put anything in front of any of these properties or methods, it might be the keyword "this" with a dot, but that's not really necessary either, as, if it's omitted, it's understood.

Next, open a new FLA file. Draw a filled circle on the stage. I drew a circle with a red fill. Select it and press F8 to convert it to a symbol. Choose MovieClip, give it the name Circle. Don't click OK yet, hang on. If this dialog box is in basic mode, click the advanced button. If you're already in advanced mode, you'll see a "basic" button instead. Having the dialog box in advanced mode means you can also set some linkage properties while you're here. Click the box that says Export for Actionscript. This will open up the other fields "Class" and "Base Class." Leave the Base Class field alone for now, but in the one that says Class, type:
com.mysite.mouse.ClipDragger2 (see below).



This establishes a direct link between the MovieClip in the library, and the class you just made. Now, the symbol is the class and the class is the symbol. Press CTRL-ENTER to test the movie. Your MovieClip that's still on the stage will now be draggable. Close the test movie. Drag some more instances of your clip from the library to the stage. Test the movie again. Now all the instances of your MovieClip will be draggable. Each one that you drag will come to the front of the stacking order, just like before.

There is one problem, though, that won't become evident until you attempt to create an instance of your class programmatically instead of adding it to the stage manually in the authoring environment. To demonstrate, remove every instance of your MovieClip from the stage, so that the stage is empty. Click on the timeline's first frame and press F9 to get the actions panel. Type in the following:
[as]import com.mysite.mouse.ClipDragger2;
var cd2:ClipDragger2 = new ClipDragger2();
addChild(cd2);[/as]
When you try this, you will get the following error message:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at com.mysite.mouse::ClipDragger2$iinit()
    at Untitled_fla::MainTimeline/Untitled_fla::frame1()

What could be the problem here? It says that we're getting a null object reference, but it doesn't say what's causing it. Whenever you get a null object reference, it means that your code has referred to an object that isn't there. But why does the class work when we drag an instance from the library to the stage, but not when we make one programmatically? The answer is the third line of the constructor, where we refer to the stage property of the clip. The stage property will be null if the clip hasn't been added to the display list yet (with addChild).

So what happens is this: Our code on the main timeline tells flash to create a new instance of our ClipDragger2 class. As soon as the new keyword is encountered, flash starts making a new instance. That means that the constructor of our class is run immediately. Inside that constructor, we refer to the stage property, and in fact we attempt to add a listener to it. But since the addChild command in the main timeline hasn't run yet (although probably only a nanosecond or two behind--haha), our MovieClip hasn't yet been placed on the stage, and so its stage property is null. Since flash has no reference to the stage at this point, it rightly refuses to add a listnener to something that isn't there, and we get a nasty error message instead of joy.

The reason it worked before was because the MovieClip was placed on the stage manually. This is basically the equivalent of addChild, albeit a manual one. Since the addChild came before the constructor was run, there was already a reference to the stage, and it worked. So how do we fix our class so that it just works, regardless of whether we want to add the clip manually or programmatically? I'm glad you asked, haha. And I won't keep you in suspense forever.

It turns out there's an event we can use called "ADDED_TO_STAGE" (handy, eh?). This requires that we import the Event class to ClipDragger2. Then we have to listen for the ADDED_TO_STAGE event to happen. This event will fire as a result of our timeline "addChild" command. At that point, we can safely add the event listener to the clip's stage property. Here's the revised class (notice that the command that adds the event listener to the stage has been moved, and now happens after we detect that the clip has been added to the stage):
[as]package com.mysite.mouse {
    import flash.display.MovieClip;
    import flash.events.MouseEvent;
    import flash.events.Event;
   
    public class ClipDragger2 extends MovieClip {
        public function ClipDragger2() {
            buttonMode = true;
            addEventListener(MouseEvent.MOUSE_DOWN, drag);
            addEventListener(Event.ADDED_TO_STAGE, addedListener);
        }
        private function addedListener(event:Event) {
            stage.addEventListener(MouseEvent.MOUSE_UP, drop);
        }
        private function drag(event:MouseEvent) {
            parent.setChildIndex(this, this.parent.numChildren - 1);
            startDrag();
        }
        private function drop(event:MouseEvent) {
            stopDrag();
        }
    }
}[/as]
Save the class file, and test the movie again. With the stage empty, the code in the fla file's main timeline programmatically creates an instance of our class, adds it to the display list, and this time it just works. The freshly minted circle appears on the stage, and you can drag it around at will. Joy!

And now you should know how to get rid of a lot of those pesky null object reference error messages. Be sure and tell all your friends!

On the next page, I'll explain the difference between the fields "Class" and "Base Class" in the linkage dialog box.

The Linkage Dialog: Setting the Class vs. Setting the Base Class
Now we have a MovieClip in the library of the fla that's linked to a class. Not only that, but we can drag out as many instances of this class as we want, and they'll all be draggable. Furthermore, we can create instances programmatically and add them to the stage programmatically too. Whether you realized it or not, you could even write a simple "for" loop and programmatically create, say, 10, 20, or even 500 instances of your class and add them to the stage. Delete the code on frame 1 of the fla file and enter this instead:
[as]import com.mysite.mouse.ClipDragger2;
for (var i:int = 0; i < 20; i++) {
    var cd2:ClipDragger2 = new ClipDragger2();
    addChild(cd2);
}[/as]
Test the movie. This creates 20 instances of ClipDragger2 and stacks them atop one another. You can confirm that there's more than one if you start dragging them around. While making too many copies of this clip might be a frightful waste of memory and bad practice, it just might be starting to spark some cool ideas for you, as well.

But back to the topic at hand. Delete that fun code and let's get back to business. Let's suppose that you're ecstatic about being able to create draggable clips just by linking them to this class. Draw a blue square on the stage, select it, and press F8 to convert it to a symbol. Next, you attempt to enter the same information as before, to link your symbol to the custom class:



Only this time, when you click the OK button, you get a message from Flash that looks like this:



So, it seems to be that the rule is this: Each library symbol can only have one custom class linked to it. What to do, what to do? It turns out that in this case, the Base Class field is going to come in quite handy. Change the two fields so that they look like this instead:



This time, when you click the OK button, Flash replies with this:



Click OK. What this dialog means is that flash couldn't find any class called "Square" in the classpath. It further explains that a class with that name will be automatically created for us at compile time, and by clicking OK we accept this generous offer. I recommend you never check "Don't warn me again," as this dialog box is really a great indicator of whether or not Flash finds a class of the same name in the classpath. If you don't get this warning, better choose a different name!

Really, what's happening here is that by having both Class and Base Class fields, we are given the opportunity to use yet another level of inheritance. That way, we can link more than one symbol to the same class, by just using the Base Class field instead, and just giving the Class field some more generic name, and letting flash create the Class.

In this case, Flash has made a class for us called "Square." The base class of Square is our custom class (long name com.mysite.mouse.ClipDragger2). And since our custom class extended MovieClip, the base class of that is flash.display.MovieClip. Can you see the chain of inheritance here? If not, think about it some more:

Our class extends MovieClip (this is written in the class file itself)
The Base Class extends our class (Base Class field of dialog box)
The Square class extends the Base Class (flash makes a Square class if you don't define one elsewhere).

Now, let's go back and change the linkage of the Circle clip, too, changing the base class to our custom class and letting Flash create a "Circle" class for us! This has the further advantage that we no longer need to import anything in the fla file's code. We can make new instances of the Circle and Square by just writing:
[as]var circle:Circle = new Circle();
var square:Square = new Square();
addChild(circle);
addChild(square);[/as]
It should be obvious why we no longer need to import anything. Now we aren't dealing with ClipDragger2 directly anymore. Now we're dealing with classes called Circle and Square, and they are in turn are based on ClipDragger2. Flash has no trouble finding the Circle and Square classes, because it creates them for us. And the information about where to find the ClipDragger2 class was entered in the dialog box. Clear?

Obviously, you could define Circle and Square classes yourself instead of having Flash create them for you, and still use ClipDragger 2 as the base class. But in that case, you might as well do everything manually, and just have the Circle and Square classes extend ClipDragger2, and give them empty constructors. Why do all that, when Flash will do it for you? It's too much work! (If anyone knows a good reason, be sure and let me know. I can't think of one at the moment).

Once again, I hope this tutorial has sparked your imagination. If you enjoyed it, won't you write and tell me so? Or, just post a comment here. Thanks!

Jody Hall (Mazoonist)