Photo by Neeku.
AS3 enforces the ideas of Object Oriented Programming (OOP) a lot more than AS2 ever did. One of the fundamental concepts of OOP is *inheritance*, allowing classes to take the properties and methods of other classes and build upon them further.
In this post, I’ll explain the three most important keywords for using class inheritance in AS3: *extends*, *override* and *super*.
###An Example: MovieClip
Let’s take a look at the *MovieClip* class to see an example of inheritance at work. If you check out the LiveDocs for this class, you’ll see this line in the description:
**Inheritance:** MovieClip -> Sprite -> DisplayObjectContainer -> InteractiveObject -> DisplayObject -> EventDispatcher -> Object
The arrows simply mean “inherits from”, so *MovieClip* inherits from *Sprite*, which in turn inherits from *DisplayObjectContainer*, and so on, right down to *Object*.
The Object class is extremely basic, containing just a handful of properties and methods. It’s an empty shell, but because it allows for the possibility of properties and functions to be added, it’s an excellent base for more complex classes.
The EventDispatcher class builds upon *Object* by adding event-related methods (functions), like *addEventListener()* and *dispatchEvent()*.
Now, because DisplayObject inherits from *EventDispatcher*, it also contains *addEventListener()*, *dispatchEvent()*, and so on. It then builds upon this by adding methods, properties, and interfaces that allow instances to be displayed on screen — for example, *x* and *y* properties for positioning, and the *hitTestObject()* method for checking for overlaps.
The InteractiveObject class allows for user interaction, adding properties like *mouseEnabled* and *tabIndex*, and events like *click* and *keyDown*.
Then we have the DisplayObjectContainer class, which can contain other *DisplayObjects* (and descendents of *DisplayObject*, like *InteractiveObject* and *DisplayObjectContainer*) with methods like *addChild()*.
The Sprite class adds, among other things, the *graphics* property, which itself is an instance of the Graphics class that allows for the drawing of vector shapes within the object. So the *Sprite* adds vector drawing capability, and some miscellaneous interface features.
Finally we reach the MovieClip class, whose main addition is that of a timeline, allowing for animation. Therefore, it has methods like *nextFrame()*, *play()* and *goToAndStop()*, and properties like *currentFrame* and *totalFrame*.
If you want the full details of what each class does, take a look at their corresponding LiveDocs page, and turn off “Show Inherited Public Properties/Methods”.
So that’s a concrete example of how Flash uses inheritance to structure its own classes. How can we use it?
###Extends
One thing that bugs me about the MovieClip class is that, if it’s on the last frame and I call *nextFrame()*, it **stays** on the last frame. I’d much prefer it to go back to the first frame, to make it easier to loop.
Rather than just complaining, let’s make our own class, *LoopingMovieClip*, that has this feature.
We’ll need to use the *extends* keyword for this. Create a new class file like so:
package
{
import flash.display.MovieClip;
public class LoopingMovieClip extends MovieClip
{
public function LoopingMovieClip()
{
}
}
}
By writing *extends MovieClip* in line 5 (and importing the MovieClip class in line 3), our new class inherits every public (or protected — more on that here) method and property. Of course, this means that at the minute *LoopingMovieClip* has no functionality other than that which *MovieClip* already has.
I’m going to add a new function, *nextFrameOrLoopToFirst()*, that’ll do what I want:
package
{
import flash.display.MovieClip;
public class LoopingMovieClip extends MovieClip
{
public function LoopingMovieClip()
{
}
public function nextFrameOrLoopToFirst():void
{
if ( currentFrame == totalFrames )
{
gotoAndStop( 1 );
}
else
{
gotoAndStop( currentFrame + 1 );
}
}
}
}
Very simple. If you want to test it out in the Flash IDE, just create a new movie clip symbol as usual, right-click it in the library, select *Properties*, export it for ActionScript, and set its **Base** class to *LoopingMovieClip*. You can give its class any name you want, and it’ll inherit from the base class. Now add a few frames to the symbol, and try running our new function.
It works, but wouldn’t it be better if we could make the *nextFrame()* method itself do this?
###Override
If you try to do the same as before, but call the function *nextFrame()* instead of *nextFrameOrLoopToFirst()*, like so:
package
{
import flash.display.MovieClip;
public class LoopingMovieClip extends MovieClip
{
public function LoopingMovieClip()
{
}
public function nextFrame():void
{
if ( currentFrame == totalFrames )
{
gotoAndStop( 1 );
}
else
{
gotoAndStop( currentFrame + 1 );
}
}
}
}
…you’ll get the following error:
1024: Overriding a function that is not marked for override.
This is telling us that *nextFrame()* is already a function in one of the classes that *LoopingMovieClip* inherits from (and therefore in *LoopingMovieClip* itself), and we can’t have two functions with the same name. You will probably have guessed that we can use the *override* keyword to get around this. Change your function like so:
override public function nextFrame():void
{
if ( currentFrame == totalFrames )
{
gotoAndStop( 1 );
}
else
{
gotoAndStop( currentFrame + 1 );
}
}
By adding the *override* keyword, we’ve told Flash that we’re aware of the inherited *nextFrame()* function, but we’d like to replace it with our own. If you test it out now, you’ll see we don’t get any errors, and that our *nextFrame()* function acts just like our *nextFrameOrLoopToFirst()* function did before.
One thing to bear in mind here is that we need to match the “signature” of the function that we are overriding — i.e., whether it’s *public* or *protected*, the parameters it accepts, and the type of variable it returns.
For example, we might like to add an optional parameter to the function that allows it to be backwards-compatible:
override public function nextFrame( p_loop:Boolean = false ):void
{
if ( ( p_loop ) && ( currentFrame == totalFrames ) )
{
gotoAndStop( 1 );
}
else
{
gotoAndStop( currentFrame + 1 );
}
}
The idea here is that calling *nextFrame()* will not cause any looping, so our existing code will act the same with LoopingMovieClips as it did with MovieClips. Trouble is, when we test this, this error occurs:
1023: Incompatible override.
In other words, because we changed the signature of our function (in this case by altering the parameters allowed), it’s no longer identical to the original and so can’t override it. Watch out for this.
Next, let’s tackle *gotoAndStop()*. If I call *gotoAndStop( 7 )* on a 5-frame movie clip, I’d like it to go to frame 2. Sounds simple, but there’s a snag…
###Super
In theory this should be similar to what we did before. Start by defining the function:
override public function gotoAndStop( frame:Object, scene:String = null ):void
{
}
(FlashDevelop tells me the signature, but you can look it up in the LiveDocs.)
To work out which frame we actually want, we can use the *modulo* operator, represented by a percentage sign %. This is like division, but it gives us the **remainder** of the expression.
If you’re rusty on remainders, here’s a quick recap.
– 7 = ( 5 * 1 ) + 2, so 7 divided by 5 is 1 remainder 2, and 7 % 5 = 2
– 14 = ( 5 * 2 ) + 4, so 14 divided by 5 is 2 remainder 4, and 14 % 5 = 4
– 20 = ( 5 * 4 ) + 0, so 20 divided by 5 is 4 remainder 0, and 20 % 5 = 0
– 126 = ( 5 * 25 ) + 1, so 126 divided by 5 is 25 remainder 1, and 126 % 5 = 1
– 3 = ( 5 * 0 ) + 3, so 3 divided by 5 is 0 remainder 3, and 3 % 5 = 3
So if we call *gotoAndStop( someFrame )* the frame we want to actually go to is *someFrame % totalFrames*. (Well, unless the result is zero — in that case, we want to go to *totalFrames*, but let’s ignore this detail for now.)
When we try to put this in, however, there’s a problem:
override public function gotoAndStop( frame:Object, scene:String = null ):void
{
var requestedFrame:int = frame as int;
var actualFrame:int = requestedFrame % totalFrames;
gotoAndStop( actualFrame )
}
(Line 26 isn’t a real problem; Flash expects the frame to be input as an *Object* rather than an *int* — most likely so that we can pass a frame label through as a String, as RedRail points out — so here we convert the *frame* parameter to an *int* so that we can use the modulo operator on it.)
In line 28 we need to call *gotoAndStop()*, but… we’ve already overriden it! What we need to call is the **original** *gotoAndStop()* method, the one defined by *MovieClip*. This is where *super* comes in.
The *super* keyword allows us to access the methods and functions of the inherited class. It’s used like this:
override public function gotoAndStop( frame:Object, scene:String = null ):void
{
var requestedFrame:int = frame as int;
var actualFrame:int = requestedFrame % totalFrames;
super.gotoAndStop( actualFrame )
}
Also, the constructor function — the function with the same name as the class that is run when an instance of that class is created — acts like an automatically overridden function, in the sense that the constructor of the inherited class can be accessed using *super*. To do this, just call *super()*, rather than *super.constructor()* or *super.MovieClip()* or whatever. Remember to make sure the list of parameters match!
Note: if you don’t include a call to *super()* in your class’s constructor, then Flash will call *super()* **before** your constructor is run, anyway – so there’s no getting away from it.
###Wrapping Up
Admittedly the functions we’ve created here could do with some improvement. Calling *gotoAndStop( 5 )* on a five-frame movie clip will actually attempt to go to frame #0 with the code I’ve written, so be sure to change that if you want to use this in a real project. Also, *nextFrame()* could just call *gotoAndStop( currentFrame + 1 )* to simplify things, and you might want to add *prevFrame()* and *gotoAndPlay()* functions. Plus, *gotoAndStop()* needs to be edited to handle frame labels and scenes. It’s a work in progress 😛
Hopefully you find the actual concepts clear, though 🙂 If you’ve any questions, please post them in the comments.
{ 35 comments… read them below or add one }
Hi, Nice blog post, I enjoyed reading it.
I’m quite new to Flash CS4 and AS3 myself. I have to say I really do enjoy learning it. I remember Flash 5..ahh the good old days. 🙂
You can use frame label rather than frame number in goto functions, so that’s probably why input must be an object. I’d add something like if(frame is int) to prevent unexpected behaviour when a frame label is passed.
Hey David, glad you enjoyed it.
I started with Flash 5 🙂 Can’t say I have fond memories of AS1 though 😛
Thanks for explaining that, RedRail! I’ve added your tip to the main post.
Very nice Michael. Finally I got it right 😀
Once again a very helpful blog post. Just begun restructuring my project with OOP in mind and it really helped in clearing up some of the things I wondered about the keywords.
Coming from an OOP intensive programming language, I find the inheritance structure of AS3 really neat. The only downside that I see is that it only has the ability to inherit from 1 class at a time. Kinda like stacking a tower.
Thanks guys 🙂
@Kronosfere I used to feel the same way, but after talking to Nick Wiggill from Visual Harmonics I changed my mind 😉
He wrote a great post on the subject here, and another on how to actually do this in AS3 here.
Another great set of articles on the subject (though not specifically for AS3) is here, from RiverMan Media.
…and I was just reading about the new PushButton Engine which uses components too.
Hmm.. That was a really interesting read there, thanks for the link. It really opens up another way to code in AS3. =D
Very usefull post. Thank you!
Thank you both!
Please confirm your statement that “super.super.super.addChild()” is valid. As far as I know it is not possible to nest the super keyword like this: super.super
You’re right, you can’t. Sorry, that was sloppy of me. I’ve removed that from the post now, thanks for pointing it out.
Cant we do it simply like below.. That works fine when i tested.
@Asif: That’ll work, but it doesn’t add any extra functionality; it just calls the regular method. In fact, it removes functionality, because the
scene
parameter is now ignored.Hello, i was looking around in the web regarding the importance of “override” in AS3.0 however to my understanding the keyword “override” simply a way to offer name usage of existing e.g nextFrame() instead of the long nextFrameOrLoopToFirst() or does it have any more usage than this please enlighten me and sorry for the noob question 😉
Hey Scarlight,
Yep, you’ve got it! But remember, other classes might be calling e.g. nextFrame() already, expecting it to do one thing — by overriding it, you can change what happens without having to make those other classes call nextFrameOrLoopToFirst() instead.
That might be a good thing, or it might be a terrible thing. Depends how you use it 😉
myMovieClip = new LoopingMovieClip()
LoopingMovieClip.NextFrame() // uses the custom function
superClip = new MovieClip()
superClip.NextFrame() // somehow , by magic, ALSO uses the custom function.
is this possible, or am i missing the OOPoint?
thanks,
D
Michael, please disregard the last post, somehow I deleted the top half as I sent it… here’s the full question
Hi Michael, thanks for the post, it’s made a few lightbulbs go off….
I was wondering if this is possible :
Are you able to specify that objects created from the superclass ALSO use the modified functions of a subclass? e.g, in your example I assume that
superClip = new MovieClip()
superClip.NextFrame() // uses it's own, 'default' function
Is there a way to do the following??
superClip = new MovieClip()
superClip.NextFrame() // somehow , by magic, ALSO uses the custom function.
is this possible, or am i missing the OOPoint?
thanks,
D
Hey UnkleDave,
Hmm. No, I don’t know of a way to do that. Why would you like to?
Excellent!!! Heaving read too many books on AS3, I finally understood the concepts of extends, override and super from your tutorial. Waiting for more…
Thanks for this very clear explanation of something I’ve been wondering about. Well done!
Hey fakeartist, hey Ian — thanks very much! I’m very happy to hear that 🙂
thanks you so much!
Well explained 🙂 thumbs up
Oh thanks a lot Michael! Finally I got it, those three things are the central of OOP and now I know 😀
Keep writing
Thx for posting. It helps me.
Hi James,
dont you think this is a better idea, instead of using above ?
package com.zisi.data
{
import flash.display.MovieClip;
}
Hi James,
dont you think this is a better idea, instead of using above ?
}
sorry, the above code will be –
Your skribit service is not available. Please, check.
Thank you, solved my problem!
Really useful to clarify my ideas.. congratulations! And of course many thanks… 🙂
But.. I didn’t understand just one thing.. why and when should I use “super()” since when I extend a class the constructor runs by default!
In other words I didn’t understand how to override a constructor! Thanks for all 🙂
Giuseppe
@manoj: Neat idea! Yeah, that works too 🙂 And I guess it is better, since maybe
nextFrame()
does more than just callgotoAndStop()
.@Chom: Unfortunately, Skribit shut down 🙁 I’ll switch to Google Moderator at some point.
@Voles: Glad to hear it!
@Giuseppe: That is a great question. It turns out that, if you don’t include a call to
super()
in your constructor, then Flash will just run it anyway, before your construcutor code. I’ve added a note about this to the tutorial – thanks for asking!Oh thank you, James!!! Now I understood why… 🙂