Are AS3 Number Variables Real Objects or Not?
I am confused. Is the Number class really a class, that I can create instances of and expect to have reference semantics etc. like the rest of the classes in ActionScript3?
Given this AS3 code:
var foo : Number = null;
trace("foo="+foo);
The compiler outputs a warning saying “null used where a Number value was expected“, but it does compile. The trace outputs “foo=0“. Hmm, okay then, foo must be an instance of a Number class. If I change the code to have no initializer for foo, like this:
var foo : Number;
trace("foo="+foo);
The output of the trace will read “foo=NaN“, which is as expected, as this is the default value of Number variables.
But wait, this AS3 code:
if (foo == null) {
trace("oops, does not compile");
}
Actually fails compilation. The compiler complains about “Comparison between a value with static type Number and a possibly unrelated type Null“. So, I can assign null to Number, albeit with a warning, but I cannot compare with null. Okay then, foo must then not be a real reference to an object.
But wait again, the documentation says that Number is a “public final class Number“, which extends Object. But I cannot compare instances of it with null. Hugh!?
I think I am actually supposed to use the global function isNaN(), to determine stuff like this. You might be alarmed to hear then, that isNaN() applied on a Number typed variable, which have previously been assigned null, will return false.


Number, int, uint, Boolean, and String are special types. They don’t act like normal Objects. Most importantly, they aren’t nullable. Additionally, they are compared by value rather than by reference.
var a:Object = {};
var b:Object = {}
a == b //false
var c:Number = 1;
var d:Number = 1;
c == d //true
Additionally, it’s important to know that null, undefined, and 0 may all go through type conversions when you do comparisons or assignment.
//EXAMPLE 1
var nullNum:Number = null;
trace(nullNum) //0
It is 0 because null gets type converted to work as a Number. That’s why isNaN() fails.
//EXAMPLE 2
var zero:Number = 0;
if(!zero)
{
trace(”zero got type converted”);
}
This can be tricky when you actually want a nullable value. For instance, the following code works:
var styles:Object = {color: 0xff0000, alpha: 0.5};
if(styles.color)
{
//if color is defined, do something
}
…but what happens when you change the value of “color” to black?
var styles:Object = {color: 0×000000, alpha: 0.5};
if(styles.color)
{
//the code in this if statement won’t run
}
Color is now equal to zero, which is type converted and becomes false in the comparison.
In short, you’ve discovered a very tricky part of the core types. It is defined as part of the ECMAScript specification, so this stuff is documented somewhere. I’m not sure if Adobe points it out anywhere, though.
September 11th, 2008 at 22:48this might help:
http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000048.html
September 12th, 2008 at 00:07Hi,
1. var foo : Number = null;
2. trace(”foo=”+foo);
Establishes foo is really 0 (with a warning).
“You might be alarmed to hear then, that isNaN() applied on a Number typed variable, which have previously been assigned null, will return false.”
1. var foo : Number = null; //So this is really 0, established prior.
2. trace(”foo=”+foo); //prints 0
3. isNaN(foo) == false, is correct. // foo is 0, which is a Number.
The result of isNaN seems reasonable to me.
However i do see your point about the Number class itself and not being able to test for null. However as you can see above - the Number is never null
but rather 0.
I think that probably the compiler should generate an error when you assign null to a type Number rather than just a warning, which would then make it consistent with the conditional testing against null.
Nice post.
September 12th, 2008 at 02:02The way I see it, if the compiler had given you an error instead of a warning when you incorrectly tried to assign null to a special type of object that is non-nullable then you wouldn’t have written this post. For whatever reason, the compiler seems to have silently cast null to Number (0). Maybe this is a deliberate design decision to handle some border cases, hence the warning to make sure that you really did intend to do it? If you get a warning and then choose to ignore it, then you can hardly complain about unexpected results, no?
September 12th, 2008 at 06:325 is Object // => true
new int(4) // => 4
5.5.toString() // => “5.5″
These statements should be quite conclusive, instances of Number are instances of Object. That doesn’t mean that variables typed as Number, int, uint and Boolean work like variables typed as Object, for example you can’t null them.
But there’s a difference here, “myNumber is Object” tests the value of the “myNumber” variable, whereas “myNumber = null” sets the variable to null. So Number objects are objects, but variables typed Number are not like other variables, but subject to compiler and runtime optimizations.
—
Another weird detail, if you want to call a method on a number literal you can’t do
5.toString()
because the “.” is considered to be the decimal point, however
5..toString()
works fine (because “5.” is the same as “5.0″).
http://blog.iconara.net/2007/03/16/architectural-atrocities-part-7-some-types-are-less-equal-than-others/
September 12th, 2008 at 07:49Great question regarding data types. I actually just wrote a post on my wordpress to answer
September 17th, 2008 at 05:56http://k2xl.com/wordpress/2008/09/17/as3-primitives/
[...] and Flex APIs Lack in Quality and Are AS3 Number Variables Objects or Not? by Tech [...]
September 21st, 2008 at 18:47