Two Kinds of Casts
AS3 has two ways you can typecast a variable. These ways are not equivalent. Let’s take a look at how they differ:
The old cast from AS2 is in the style of C++, like a function call:
function foo(o:Object): String { return Point(o).x + Point(o).y; }
You’re just saying that you want to convert an object of one type to another. If the object isn’t really of the given type, you get null back. With the introduction of AS3, there’s a new cast in town:
function foo(o:Object): String { return (o as Point).x + (o as Point).y; }
This is what I like to think of as the “long winded” cast or the “natural language” cast. It reads as English usually does, much like the new is operator in AS3 is nicer to read than instanceof, but different. These two casts differ in a key way, though. The docs for the as operator and the C++-style cast are vague and imprecise. So let’s have a look for ourself. Consider this:
class Parent { } class Child extends Parent { } var c:Child = new Child(); trace(Parent(c)); trace(c as Parent);
This comes out just as expected: both return the input child c. However, just as you read in The Magic of is, there is some magic when it comes to built-in types:
var n:Number = 3.5; trace(int(n)); trace(n as int); var i:Number = 3; trace(int(i)); trace(i as int);
Here we see the same magic we saw with the is operator. The as operator inspects the contents of the first operand and makes its determination not solely by type (Number is not the same class as int), but also by the contents of the Number. Secondly, the int casts we’re doing here are not actually casts. They are instead the global int() function that will convert any value to an int. With that function, one gets the C-style truncation of floating point values. Here are the answers:
3 null 3 3
As with the is operator and so many other subtleties of the language, there isn’t one “correct” operator you should always use. The key is to know the difference between them. The way I remember the difference is that as is the more strict cast and C++-style “function call” casting is more of a conversion. Keep this in mind and you’ll know which you should use.
#1 by Robert Penner on September 16th, 2009 ·
Point(o) will throw an exception if the cast fails, whereas o as Point will evaluate to null and keep on trucking.
#2 by jackson on September 16th, 2009 ·
Yep, the key seems to be knowing which one you want and when. Most of the time you know that the cast is OK, but in those cases where you don’t you should use the appropriate cast. People who like exceptions will likely prefer Point(o), people who don’t will likely prefer o as Point. I’m glad AS3 give you options.
#3 by Jonnie on October 1st, 2009 ·
In a speed comparison, (o as Point) is 3x faster than Point(o). And, in your example, if you use: var p:Point = o as Point; it’ll be 4.5x faster.
#4 by jackson on October 2nd, 2009 ·
Wow, that’s a pretty huge boost! Thanks for sharing.
#5 by Vishwas on May 6th, 2013 ·
In primitive types casting is understandable.
However, casting classes from parent to child, it doesnot slashes out the properties after casting. Why ?
For example : I have a movieclip on stage with 2 frames. The name of movieclip is “mc”
var mc:MovieClip
mc.gotoAndStop(2);
trace(mc.currentFrame); // output 2 –> that’s ok
var sprite:Sprite = Sprite(mc)
trace( MovieClip(sprite).currentFrame);//output 2, value not lost, which is questionable
In the above, if i have caste movieclip to sprite, then there should not be any property called “currentFrame”. But still, it seems properties remain intact even after casting. The object remains unaffected, it’s only the type changes.
V.
#6 by jackson on May 6th, 2013 ·
With primitives, the actual value changes. With class instances, it’s just changing the type. In your example you have a
MovieClip
that you cast to aSprite
. It’s still aMovieClip
, but it’s type is nowSprite
. If you try to accesscurrentFrame
on it, you’ll get a compiler error. However, it’s still aMovieClip
so your cast back toMovieClip
succeeds. At that point it has the typeMovieClip
and therefore you can accesscurrentFrames
without a compiler error.Hope that clears things up.