Sunday, April 13, 2008

Reflection in ActionScript 3

I'm not a big fan of the old eval() function in earlier versions of ActionScript. As of ActionScript 3, it is no longer supported. For the most part, that is a very good thing. My buddy, Jason, is migrating from AS2 to AS3 and he found himself looking for the eval() function. He came to me and asked me about it, I replied "you mean the evil() function?".

The problem with eval() is that you were executing code that was being created at runtime, meaning there's no chance of the complier helping you catch errors. He showed me the code he was working on and --usually-- you can solve the lack of eval() through a better architecture. As I looked at his program, I realized he had a pretty elegant solution. Re-architecting would take a good deal of time and not necessarily yield as elegant result. Java has quite a few classes for dealing with reflection, so I figured (given how similar AS3 is to Java) there must be some similar classes. As it turns out, the pickings are pretty minimal... but there were enough to come up with a nice, dynamic solution to his problem.

In the flash.utils package, there are a number of public functions. The one we were looking for (before we even knew it) was getDefinitionByName(). This function takes a string that is the name of a class, an returns the class object for it. With the class object, you can then create an instance of the class. Here's a simple example you could run in the Flash IDE:
var myClass:Object = getDefinitionByName("Symbol1");
addChild( new myClass() );
It assumes you have a Symbol named "Symbol1" that is exported for ActionScript. If you are doing this in Flex or inside an external class file, remember to import the flash.utils package. The danger of runtime errors still exists, but it is more limited now in that you can create classes and not just execute and arbitrary chunk code on the fly like you could with eval().

2 comments:

  1. Hi, a while ago I asked some questions on your blog and it was really helpful. Recently I'm completely stuck on something again.. was wondering if you could help =)

    It seems like a simple problem. I'm trying to load different youtube videos at runtime as external swfs. But only the first one loads, others just don't get displayed.

    So I have a swfloader and two buttons to switch source.


    public function loadSWF (filename : String) : void {
    swfLoader.source=filename;
    }


    < mx:SWFLoader id="swfLoader" source="http://www.youtube.com/swf/l.swf?video_id=A72jSPEtOJI">< /mx:SWFLoader>
    < mx:Button x="688" y="505" label="1st" click="loadSWF('http://www.youtube.com/swf/l.swf?video_id=A72jSPEtOJI')"/>
    < mx:Button x="761" y="505" label="2nd" click="loadSWF('http://www.youtube.com/swf/l.swf?video_id=InY3SLWORj8')"/>


    It works fine with other swf files that don't involve youtube videos... any ideas... very much appreciated!

    ReplyDelete
  2. This might be an easy one, Sarah (and not Flash-related). After testing your links, through the browser, only the first link works!

    ReplyDelete