Tuesday, July 24, 2007

AS3 language 101 for C/C++ coders

source:
http://blogs.adobe.com/kiwi/2006/05/as3_language_101_for_cc_coders_1.html

Run time type checking

Since you can pass things around as anything using the wildcard type (void *), you need a way to check the type of the object at runtime. To do this, you can use the "is" directive:

public function doSomething() : void
{
var something:* = getData();

if (something is String)
{
// handle string logic
}
else
{
// do something else
}
}

This allows for runtime type checking which allows your application to perform different logic depending on what the given object is.

Typecasting

In AS3, think of typecasting like calling the constructor of the type. Functionally, this isn't what happens, but the syntax is what it appears to be doing.

In C: int i = (int)somefloat;
In AS3: var i:int = int(somefloat);

If you see what appears to be something calling the constructor of a class or type but it does not use "new", it's not calling a constructor. It's performing a typecast. For example:

var foo:SomeClass = SomeClass(someObject);
var bar:SomeClass = new SomeClass(someObject);

The first line is typecasting "someObject" into SomeClass. The second line is creating a new SomeClass object, passing "someObject" as a parameter to the constructor. This subtle difference can have wide ranging effects (new object vs. reusing an existing object, etc.). Depending on what the class constructor takes as a parameter, it is possible that both the typecast and the constructor would compile with no errors/warnings in all situations. So, be careful. The difference between a typecast and a new object is just the "new" keyword.

dynamic_cast

In AS3, you will find yourself dealing with interfaces. These are similar in concept to abstract base classes in C++. Objects that implement an interface will be passed around as instances of that interface. So, given an object of a specific interface, how do you get the object as an instance of its subclass? You use the "as" functionality. For example:

var someInterface:ISomeInterface = factory.getSomeInterface();
var someClass:SomeClass = (someInterface as SomeClass);

If "someInterface" is actually an instance of "SomeClass" or a derived class of "SomeClass", the variable "someClass" will be a reference to that object. If "someInterface" is an instance of some other class, the "someClass" variable will be null.

Comments

I just wanted to add one note about the as operator described above in the section titled "dynamic_cast":

The as operator, which is used to cast an object to a type at runtime, can be used not only to cast an instance of an interface (as in the example above) but also to upcast or downcast any type to a possibly related type (i.e. a subclass or superclass). So in the code below, either of the as statements would properly cast the instance:

public class ParentClass {}
public class ChildClass extends ParentClass {}
...
var child1:ChildClass = new ChildClass();
// note this is a ChildClass instance, upcast as ParentClass
var parent1:ParentClass = new ChildClass();
...
var parent2:ParentClass = (child1 as ParentClass);
var child2:ChildClass = (parent1 as ChildClass);

Of course, the second as statement only works because parent1 was declared as ParentClass but instantiated as a ChildClass instance.

For me personally I think of is and as as a pair of related operators; one tells you whether something is an instance of a type, the other one tells you and casts the object all in one operation.

(Sorry about the short note that turned into a long note. I'm sure you already know all of this anyway, but I thought it might not be precisely clear to everyone, based solely on the context of the article.)

In any case, thanks for the articles, and I'm excited to read more!

No comments: