ActionScript 3, Tools, Tutorials

Check a Class type with describeType and getQualifiedClassName

Recently I faced this problem: how to get if a Class is extending another one or implementing an interface?

this is the specific case:

function checkType(toCheck:Class,typeClass:Class=null,typeInterface:Class=null):Boolean
{
// if an instance of toCheck is a typeClass or a typeInterface
// return true
// else
// return false
}

The task is quite simple, the first solution would be get an instance of toCheck and use the is operator to actually check the type…but this would mean both a waste of resources and an “unwanted behaviour generator” (just think about a parser class instantiated without a real need or something like that).

Nope, that solution sucks.

Let’s try something better, let’s make the player inform us which is the toCheck class structure, let’s use describeType.

describeType is a wonderful function you can find in flash.utils package, it examines an untyped object and returns an xml document containing the description of that type (more details at adobe livedocs)…something like this:

NOTE: click on “view code” to see the real xml document, my wp is escaping tags chars <> …:

<type name="flash.events::EventDispatcher" base="Class" isDynamic="true" isFinal="true" isStatic="true">
  <extendsClass type="Class"/>
  <extendsClass type="Object"/>
  <accessor name="prototype" access="readonly" type="*" declaredBy="Class"/>
  <factory type="flash.events::EventDispatcher">
    <metadata name="Event">
      <arg key="name" value="deactivate"/>
      <arg key="type" value="flash.events.Event"/>
    </metadata>
    <metadata name="Event">
      <arg key="name" value="activate"/>
      <arg key="type" value="flash.events.Event"/>
    </metadata>
    <extendsClass type="Object"/>
    <implementsInterface type="flash.events::IEventDispatcher"/>
    <constructor>
      <parameter index="1" type="*" optional="true"/>
    </constructor>
    <method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="String" optional="false"/>
    </method>
    <method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="String" optional="false"/>
    </method>
    <method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Function" optional="false"/>
      <parameter index="3" type="Boolean" optional="true"/>
    </method>
    <method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
      <parameter index="1" type="flash.events::Event" optional="false"/>
    </method>
    <method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
      <parameter index="1" type="String" optional="false"/>
      <parameter index="2" type="Function" optional="false"/>
      <parameter index="3" type="Boolean" optional="true"/>
      <parameter index="4" type="int" optional="true"/>
      <parameter index="5" type="Boolean" optional="true"/>
    </method>
    <method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
  </factory>
</type>

As you can see in this EventDispatcher type description there are two nodes witch are fitting the task’s purposes:

<extendsClass> and <implementsInterface>

Those nodes are repeated for each class or interface in the given class (toCheck) chain of inheritance and they contain the qualified class name string of the extendedimplemented classinterface.

In this case EventDispatcher extendsClass type=’Object’ and implementsInterface type=’flash.events::IEventDispatcher’ …quite clear right?:) Now, back to the implementation:

function checkType(toCheck:Class,typeClass:Class=null,typeInterface:Class=null):Boolean
{
	//gets the toCheck class type xml description
	var _typeXML:XML=describeType(toCheck);
	//gets the typeClass and typeInterface qualified class names
	var _result:Boolean=false;
	if (typeClass) {
		// if toCheck is a typeClass
		for each (var _extClass:XML in _typeXML.factory.elements('extendsClass')) {
			if (_extClass.@type==getQualifiedClassName(typeClass)) {
				_result=true;
				break;
			}
		}
	}
	// do the same for typeInterface but checking 'implementsInterface' node
	if (typeInterface) {
		for each (var _impInterface:XML in _typeXML.factory.elements('extendsClass')) {
			if (_impInterface.@type==getQualifiedClassName(typeInterface)) {
				_result=true;
				break;
			}
		}
	}

	return _result;
}

…and the task got done 🙂

stay tuned 🙂

Advertisements

One thought on “Check a Class type with describeType and getQualifiedClassName

  1. Hi Mr. Piergiorgio (guess it’s your name).

    Good article.

    Just wanted to point out one possible fix (if it’s of any help).

    I think that in the second “for each” iteration the string should be “implementsInterface” instead of “extendsClass”.

    Enjoy your FlashONTHEBeach 09. Greetings from Spain.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s