In ActionScript 3, classes (and functions as well) are objects that can be manipulated like any other object. The language provides us with some constructs to facilitate this, and they are an important part of the programmer’s toolkit.
We need to be able to traverse the connections among the Class, an instance of the Class, and the name of the Class.
From name to Class; from instance to Class
First, you want to be able to get hold of a Class object, either from its package path and class name:
import flash.utils.*;
var myClass:Class = getDefinitionByName("com.myDomain.myPackage.SomeClass");
or from an instance of the class:
var myClass:Class = myInstance.constructor;
Here are a few simple ways you can use these:
-
The Class object is a factory for making instances of its class, so using getDefinitionByName() you can write a factory method to instantiate objects of types specified by Strings, e.g. in an XML file:
var myClass:Class = getDefinitionByName("com.myDomain.myPackage." + xmlData.@type); var myObject:Object = new myClass(); -
Run-time enforcement of an abstract class:
public function MyClass() { super(); if (this.constructor == MyClass) { throw new IllegalOperationError("AbstractException"); } } -
Suppose a game character is collecting items such as gems or weapons or vegetables, and all you need to know about the items is their type. You don’t have to hang on to the items themselves; you can store the collection as a Dictionary indexed by class objects:
private var _collection:Dictionary = new Dictionary(true); . . . private function collect(item:Object):void { var itemClass:Class = item.constructor; if (_collection[itemClass] == null) { _collection[itemClass] = 1; } else { _collection[itemClass]++; } }
From Class to class name; from instance to class name
I’ll just show my getClassName() function here:
import flash.utils.*;
public function getClassName(o:Object):String
{
if (o is Class)
{
var s:String = o.toString(); // "[class SoAndSo]”
return s.substring(7, s.length - 1);
}
else
{
var fullClassName:String = getQualifiedClassName(o);
var i:int = fullClassName.lastIndexOf(”::”);
if (i == -1)
{
return fullClassName;
}
return fullClassName.slice(i + 2);
}
}
The toString() method is defined in the root Object class, and it can be redefined in your own classes. It’s called whenever the String representation of an object is needed. For example in getClassName() I could have written
var s:String = "" + o;
which would have implicitly invoked o.toString(). The trace() function also uses toString(). So it’s a good idea to implement toString() in your classes. I usually start out by doing this:
public override function toString():String
{
return getClassName(this);
}
and then add whatever specific data I need to show into it.
Related ActionScript 3 Tip of the Day by Senocular: #73
From Class to Class
Here’s the last basic class-slinging tool, and I believe it’s one that not many Flash programmers are aware of. Suppose you want to know if class A is derived from class B. You might think you’d have to make an instance of A and use the is operator on it. And that’s OK if you don’t have to come up with parameters for the constructor. But there’s a cleaner way:
public function isDerived(childClass:Class, ancestorClass:Class):Boolean
{
if (ancestorClass.prototype.isPrototypeOf(childClass.prototype))
{
return true;
}
return false;
}
Now you may say yeccch, we’ve left the prototype behind, that’s old-school AS1 programming, and you’d certainly be correct in a way: In AS1 there was no way to simulate classes except by mucking with the prototype, and in AS2 the compiler simulated classes under the hood by mucking with the prototype, and in AS3 we have true class inheritance. So there’s almost certainly no need to simulate classes in AS3. But the prototype, and the isPrototypeOf() function, are not going away any time soon; they’re in the ECMA spec, so they must be retained in the language. I believe I can guarantee, though, that aside from this isDerived() function, there is NO other legitimate use case for isPrototypeOf() in AS3! The prototype itself is a different matter, and I mentioned a use case for placing properties there in a comment to my recent post Advanced Users May Choose.
Related ActionScript 3 Tip of the Day by Senocular: #74
What can you do with isDerived()? Suppose my game character is collecting various kinds of Gems, such as Rubies, Sapphires, and Diamonds, and various kinds of Vegetables, such as Rutabagas, Kohlrabi, and JerusalemArtichokes. He’s saving them in a Dictionary as in the example above, and I need to know how many Gems or how many Vegetables he has:
private function numInCollection(collectionClass:Class):uint
{
var n:uint = 0;
for (var key:* in _collection)
{
var c:Class = key as Class;
if (c == collectionClass
|| isDerived(c, collectionClass))
{
n += _collection[key];
}
}
return n;
}
Summary of indexed collections in AS3
- Object: properties indexed by Strings
- Array: properties indexed by Numbers
- Dictionary: properties indexed by Objects
Occasionally I meet a programmer who indexes an Array object’s properties using Strings. Of course this works, but it works because the array is an Object; if you’re not using Numbers as indices, then you’re just wasting space by declaring the collection as an Array. You could make it a MovieClip and it would work just as well!


I think
“Dictionary: properties indexed by Objects”
might be a bit misleading. I could be wrong, but I always thought that Dictionary has properties indexed by the toString value of objects. If you have two objects with the same toString, will they be different in the Dictionary object? That’s how I always envisioned it; I think Java is similar in that regard.
Comment by Danny Miller — June 16, 2008 @ 12:17 am
I don’t know about Dictionaries in Java, but in AS3, this is precisely what distinguishes a Dictionary from an Object. To quote the Flex 3 Language Reference:
The Dictionary class lets you create a dynamic collection of properties, which uses strict equality (===) for key comparison on non-primitive object keys. When an object is used as a key, the object’s identity is used to look up the object, and not the value returned from calling toString() on it. Primitive (built-in) objects, like Numbers, in a Dictionary collection behave in the same manner as they do when they are the property of a regular object.
Comment by alan — June 16, 2008 @ 12:36 am
[...] is here [...]
Pingback by Series of ways to use Classes from assorted objects : Mark Badger:Comics & Code — June 16, 2008 @ 12:53 am
About the Dictionaries, instead of Objects (which could be confusing) you could say instances. Dictionary is not using the toString method to determine the uniqueness of the key.
About the prototype.isPrototypeOf method: too bad it doesn’t work for interfaces…
Greetz Erik
Comment by Erik — June 16, 2008 @ 5:50 am
Erik -
About the Dictionaries I could say instances — of Object! About the Object I could say instances of String. About the Array, I could say instances of Number. I don’t think that would add anything :)
Comment by alan — June 16, 2008 @ 8:31 pm