Types of types

I saw this post about Numbers, ints, and uints:

http://troyworks.com/blog/?p=67

and started thinking up a nice answer but then saw that the blog does not accept comments. So I’ll post my comments here. The basic point was creating a variable as a Number, assigning it an integer or unsigned integer value (and vice versa) and then tracing out what type it held.

The following code was used:

[as]var a:int = 1;
var b:uint = 2;
var c:Number = 3;
var d:Number = 4.5;
var args:Array = [ a, b, c, d];

function testNumber(a:Object):void{
trace(a + ” ——”);
trace(” isNumber?” + (a is Number));
trace(” isInt?” + (a is int));
trace(” isUint?” + (a is uint));
trace(” typeof number? ” + (typeof(a) == “number”));
}

for(var i in args){
testNumber(args[i]);
}[/as]

The author was surprised, I think, that in cases 1, 2, and 3, the result showed that the value was both a number and an int / uint.

There are two factors here. One is inheritance. Although the documentation says that int, uint, and Number all inherit from Object, it’s obvious that there is some relationship between the three. Otherwise the following code would not compile:

[as]var a:int = 1;
var b:Number;
b = a;[/as]

I think it is safe to imagine an inheritance structure between these three, where Number is the most general type, int is more specific, and uint is more specific still. Thus an uint “is a” int, which “is a” Number, in the same way that a MovieClip “is a” Sprite, because it extends it:

[as]var m:MovieClip = new MovieClip();
trace(m is Sprite); // true[/as]

That accounts for why variables typed as ints/uints and assigned ints/uints trace true for being Numbers.

But what about the third case, where a Number variable is assigned the value 3, and then traces out true for int and uint? Well here we have the difference between a variable and a value. A variable is a container. You can give it a type, which tells you what type of objects that container can hold. That doesn’t tell you the actual type of the object it is holding though. It may be holding a related, more specific type. Altering the last example a bit:

[as]var m:Sprite = new MovieClip();
trace(m is MovieClip); // true[/as]

The variable m is assigned the type Sprite. But it is actually holding a MovieClip. The variable has a type, but the trace occurs a runtime and looks at the actual object and its type, not the container’s type.

In the author’s example, the value 3, is an int, and a uint. The variable is typed as Number, but at runtime, the trace method looks at the object in there, which is indeed an int/uint, and reports what it finds.

This entry was posted in Flash. Bookmark the permalink.

9 Responses to Types of types

  1. jon says:

    So do you think that the new movieclip isn’t upcast as a sprite on instantiation? I guess that makes sense, but wouldn’t assigning a value of 4.5 to an int cast it to a whole 4?

    i’d check right now, but no flash running on this machine 🙁

  2. kp says:

    The movie clip is cast as a sprite, sure. But the object itself remains a movie clip.

    assigning 4.5 to an int does not cast it to a whole 4, it converts it to a 4, as you can see here:

    var a:int = 4.5;
    trace(a); // 4
    var b:Number = a;
    trace(b); // 4

    int is a more specific type so you can’t cast a more general type (Number) as an int. Seems to me that should actually fail, but it does compile.

  3. kp says:

    Of course, in the movieclip / sprite example, you could only address it as a sprite. This is more of the compiler’s job to make sure that you aren’t performing functions on a variable of a type that doesn’t support actions on that type of object. So you couldn’t say

    var s:Sprite = new MovieClip();
    s.gotoAndPlay(1);

    Again, the compiler will stop you from doing this. But at runtime, it is still a movie clip. You can address it as one by casting it.

    MovieClip(s).gotoAndPlay(1);

    But, if s does not actually hold an instance of MovieClip, then you’ll get a runtime error. Because it could hold any sprite or any subclass of sprite, which might not have a gotoAndPlay method.

  4. jon says:

    right, i hear ya there. good test with calling the movieclip function on the variable. i guess it still surprises me though that you could cast it and have the method available.

    and by whole number, i just meant an int, or a rounded number. guess i gotta read up on my number terminology.

    thanks for bringing that to light, i’ve been doing some work lately where i’ve been wondering the same thing every time i create the container variable, but have been too assuming to check it myself 😉

  5. kp says:

    I think the big thing to remember is that a variable type specifies what type of objects that container can hold, but an object type is the actual type of that object at runtime. a variable HOLDS an object, but it is not that object.

  6. kp says:

    It also helps to study some lower level languages like C or C++. There you learn that a variable really just holds a memory address. The object it refers to is located at that address. The variable type just says what kind of things it can point to. It doesn’t change the type of object that is at that address.

  7. Richard Lord says:

    Keith. On the surface, it seems more straightforward than you are making it.

    “typeof” returns number for all numeric types, that’s how it’s defined to work.

    “is” does not indicate whether an object is of a specific type, it indicates whether an object is compatible with a specific type, and 1, for example, is compatible with int, uint and Number and hence returns true for all three, while 4.5 is only compatible with Number.

    Also, note that int, uint and Number are all defined as final, so they shouldn’t be extending each other.

    Which seems to explain it but…

    Try “instanceof” on the four variables. This is the (deprecated) method that actually looks at the prototype chain of the object. It indicates all four variables are instanceof Number and none are instanceof int or uint.

    Which suggests that either instanceof is broken (which would explain it being deprecated) or int and uint really are just synonyms for Number, presumably with hinting for the flash player to optimise them differently.

  8. Troy Gardner says:

    Hey Keith,

    Thanks for the response. I have comments temporarily turned off due to 30 spam messages a day, and plans to upgrade the site/Wordpress around the first of the year.

    I do understand that Sprite>MovieClip., But as you point out in the documentation that Number, int, uint do not extend from each other, and are not declared as interfaces. Assigning can be implicit casting/conversion in some languages (e.g to String).

    This is why I was surprised. The documentation makes them ‘appear’ as separate types, but in practice there is some type conversion on the fly which is not documented as far as I can tell and the output doesn’t match strict type casting.

    I imagine there is are 2 lower level number, string primitive versus Number, String, with functions. We don’t have access to these directly anymore.

  9. I went through this back in April and posted my findings here: http://natejc.com/blog/?p=32

Leave a Reply