ActionScript 3.0 adds a number of features to support object-oriented ("OO") programming. Even if you are not creating lots of your own classes, much of ActionScript 3.0's functionality is built into a set of classes that have established inheritance relationships. To use these Flash classes effectively, it's essential to understand how types and typecasting work.
Look at the DisplayObject class, for an example. DisplayObject has the following direct subclasses:
- AVM1Movie
Bitmap
InteractiveObject
MorphShape
StaticText
Video
And that's only the subclasses that extend DisplayObject directly. If you look at subclasses of subclasses, you'll find that (among others) Loader, Sprite, and Stage are also indirect subclasses of DisplayObject ("great grandchildren" if you like: DisplayObject -> InteractiveObject -> DisplayObjectContainer -> Sprite). MovieClip is another indirect subclass of DisplayObject (through Sprite).
Point #1: Objects can be treated as if they are objects of any of its parent classes. So, for the following DisplayObjectContainer method:
ActionScript Code:
addChild(child:DisplayObject)
the argument "child" can be a Bitmap, or a Loader, or a StaticText, or any other subclass of DisplayObject. All of these things, in an important sense,
are DisplayObjects.
Point #2: Objects cannot be treated as if they were objects of a particular subclass without typecasting. The situation described in point 1 doesn't work when you move in the other direction. While you can treat a MovieClip as a DisplayObject, you can't take a DisplayObject and use it as a MovieClip. For example, the following code would fail (would not compile):
ActionScript Code:
function playClip(clip:DisplayObject):void
{
clip.gotoAndPlay(0); // doesn't work - "clip" is a DisplayObject, not a MovieClip!
}
Note that in the "playClip" example, the object pointed to by the argument "clip"
might actually be a MovieClip, as it would be if you called it like this:
ActionScript Code:
playClip(new MovieClip());
However, even if that is the case, the
variable "clip" still has the type "DisplayObject", and that type does not have a "gotoAndPlay" function.
Point 3: Typecasting can convert a variable of a superclass type into a variable of a subclass type. Typecasting is a way of translating or recharacterizing a variable into a related type. There are a couple of ways to do this, but I prefer the "is" and "as" operators. Here's the "playClip" example modified to use the typecasting operators:
ActionScript Code:
function playClip(clip:DisplayObject):void
{
if( clip is MovieClip )
{
var mc:MovieClip = clip as MovieClip;
mc.gotoAndPlay(0); // "mc" is type MovieClip, so we can call gotoAndPlay
}
else
{
trace("Error, " + clip + " is not a MovieClip.");
}
}
The "as" operator will just return null if the thing you're trying to cast is not actually an object of the requested type, so you don't even really have to use the "is" operator in this example:
ActionScript Code:
function playClip(clip:DisplayObject):void
{
var mc:MovieClip = clip as MovieClip;
if( mc != null )
{
mc.gotoAndPlay(0);
}
else
{
trace("Error, " + clip + " is not a MovieClip.");
}
}
Finally, a common real-world scenario. Suppose that you have made a custom class, "MyDocument", that you are using as the document class for a Flash file:
ActionScript Code:
package pkg {
public class MyDocument extends MovieClip
{
public var filenames:Array;
public function reloadFile(var filename:String):void
{
//...
}
}
}
That means that for objects put on the stage in the flash file, the "root" object will be a MyDocument.
However, the "root"
property is still of type DisplayObjectContainer, so it cannot be used to access MyDocument functions or properties without typecasting:
ActionScript Code:
// this code is on the timeline of a MovieClip symbol we are placing on the stage.
import pkg.MyDocument;
function updateStatus():void
{
var theDocument:MyDocument = root as MyDocument;
if( theDocument == null )
{
trace("error, root isn't a MyDocument!");
return;
}
for each( var filename in theDocument.filenames )
{
if( isFileOutOfDate(filename) )
{
theDocument.reloadFile(filename);
}
}
}
Live docs page:
http://livedocs.adobe.com/flash/9.0/main/00000045.html