When you pass an object of a subtype (or iterate a list of subtypes, etc.), no casting or conversion is required -- the object is that subtype, and can be passed directly. The reason for this is that the memory layout of objects with inheritance is usually implemented as the base object's data, then the next inheriting class's data, etc. plus a vtable pointer to allow method overriding/interface implementation:
// class Sub : Base
obj -> +----------+
|vtable ptr| -. vtable
|----------| `-> +---------+
|Base data | | Method1 |
|----------| +---------+
|Sub data | | Method2 |
+----------+ +---------+
When passing a Sub object, the underlying pointer points to the start of the object in memory -- which is exactly the same as the Base object's start in memory, so there is nothing to do when converting between Sub to Base internally; the only difference is how the variable is used (type checking semantics). The actual object value, and references to it, need absolutely no conversion (in a sane implementation, anyway).
Adding a cast would only slow things down (unless the compiler is smart enough to remove the cast, which it should be, but I don't have much confidence in the optimization capabilities of the AS3 compiler).
However, casting Number
s to int
s and vice versa is completely different, as that requires converting the internal representation of the values -- which is slow.
Note the difference between references to objects (where the variable's actual value is just a handle to that object), and value types (where the variable's actual value is the value itself -- no indirection). For example, an int
variable holds the actual integer variable, whereas a variable of type Object
merely holds a reference to some object. This means that if you use variables of type Object
(or untyped variables which are of Object
type by default), and try to stick an integer in them, this will cause what's called a "boxing" operation, which takes the value and sticks it into a temporary object so that the variable can keep a reference to it. Manipulating it like an integer (or explicitly casting it), causes that boxed value to be unboxed, which obviously is not instant.
So you can see, casting objects to their base is not slow, because there's no work to do. Casting a base to a derived type is almost as fast (because nothing has to be done to the internal pointer there either), except that a check has to be done to ensure that the object really is of the derived type (resulting in an exception or null depending on what type of cast was done). Casting value types to object types and vice versa is not very fast, because work has to be done to box/unbox the value in addition to a runtime type check. Finally, casting one basic type to another is particularly slow, because the internal representations are completely different, and it takes correspondingly more effort to do the conversion.