Categories Displayed in Flash

Archive for the 'flex' Category

Java vers AS3 comparison

This Is a great overview of Java vers AS3 on a language feature level. In many cases I prefer AS3 over Java, method closure, anything for a switch type, strict equality === being some of my favorites.

Introspection in AS3: use of namespace

As I was mentioning in the last article, I was looking for ways to introspect code without resorting to use of 'public' access modifier /namespace.
This is for a particular project/framework named Cogs which I'll be covering more. Cogs is a statemachine, and allows for multiple active states, similar to putting animated movieclips inside other animated movieclips. Cogs uses functions in a very unique way, in that every function is a 'state' similar to a frame in Flash, and every state has events similar to 'enter_frame' and 'exit_frame'. A variable maintains a link to a current function, and passes events to it. So a Person class might have the following lifecycle, each state corresponding to a function.

  • s_eating(evt:Event); //parent is s_awake
  • s_awake(evt:Event); //parent is s_alive
  • s_sleeping(evt:Event);
  • s_alive(evt:Event);
  • s_dead(evt:Event);

While Cogs has a reference to the current state (say eating), which bubbles events. If scoped to the public namespace, apps using Persons could inadvertently call other inactive states directly , causing undersired responses, when preferrably unauthorized calls to the function shouldn't compile at all.
Say if the person is currently in the 'dead' state, and someone asks "How are You?" Event/Request, it doesn't reply, but if they call s_awake, it might respond/trace "great!".Normally
Part of the problem somewhat unique to using Cogs's is validating the hierarchy making sure there are no dead ends. E.g. this is a good heirarchy.

  • Root
    • Dead
    • Alive
      • Sleeping
      • Awake
        • Eating

This would be a malformed one.

  • Root
    • Dead
    • Alive
  • Awake
    • Sleeping
    • Eating

flash.util.Proxy
So I was originally going down the path of using flash.util.Proxy's neat feature to 'iterate' over an object thinking it had special powers of visibilty with all it's capabilities of overriding iterators and the like. When actually it is just a Proxy, relaying requests to variables and methods frequently of child attributes/methods, other than itself.
Proxy in use should be composition primarily instead of inheritance. It's supposed to wrap other classes instead of be the class. This is kinda a way to achieve the appearance of multiple inheritance, via proxying requests to multiple classes. Anyway the for..in and describeType limitations still apply, there is nothing magical about the namespace/scope of Proxy or flash_proxy other than they aren't public so won't collide if methods are similarly spaced. However I noticed that tracing out methods namespaced to flash_proxy were showing up on the describeType. Which game me a clue to where to go.

AS3 namespace, creating, using.

The documentation on namespace in regards to AS3, and multiple classes is a bit hard to find. Especially on the web/google. But it's very cool (check the Flash CS3 help for examples)

starting here

http://livedocs.adobe.com/flash/9.0/main/flash_as3_programming.pdf

and here

Here's the basic steps to creating and using namespaces. Quote:

There are three basic steps to follow when using namespaces. First, you must define the
namespace using the namespace keyword. For example, the following code defines the

version1 namespace:
namespace version1;

Second, you apply your namespace by using it instead of an access control specifier in a
property or method declaration. The following example places a function named
myFunction() into the version1 namespace:

version1 function myFunction() {}

Third, once you’ve applied the namespace, you can reference it with the use directive or by
qualifying the name of an identifier with a namespace. The following example references the
myFunction() function through the use directive:

use namespace version1;
myFunction();

You can also use a qualified name to reference the myFunction() function, as the following
example shows:

version1::myFunction();

What this doesn't cover is how to create namespaces, and URIs. The help documentation has two types of namespaces, that primarily used for XML and that used for actionscript visibility even though underlying they are probably the same thing. It took me an hour to figure out how to figure out how flash_proxy namespace was implemented, as that's not covered directly.

I created two folder/packages Test and Introspectable, Test containing the main executeable and Introspectable having a namespace, and a class that uses namespace to limit visibility for variables and such. My first goal was creating a namespace that is visible to multiple classes in multiple packages silmiar to flash_proxy, which was the trickiest part, as it's not a class. But rather AS3's somewhat unusual ability to import straight functions/etc. Similar to #include in AS2.
//FILE1: Introspectable/introspectable.as

package Introspectable {//note that default URIs are {package}.{namespace defined in this file}
//e.g. URI Introspectable.introspectable but I'm overriding it with URI of "com.troyworks.cogs"
public namespace introspectable = "com.troyworks.cogs";
}

//FILE2: Introspectable/

package Introspectable{
import Introspectable.introspectable;

public dynamic class IntrospectableObj {

introspectable var introVar:Number= 0;

introspectable function s_introspectable():void{
trace("Hello World from introspectable::s_introspectable");
}

//File3: Test/Test_DescribeType.as

package Test {
import flash.display.Sprite;
import flash.utils.describeType;
// import Introspectable.*;
import Introspectable.IntrospectableObj;
import Introspectable.introspectable;public class Test_DescribeType extends Sprite{

public function Test_DescribeType(){
super();
var intro:IntrospectableObj = new IntrospectableObj();
var desc:XML = describeType( intro);
trace("Test_DescribeType \r" + desc);
// use namespace introspectable;
intro.s_introspectable();

OUTPUT

note you can see the ones with the custom namespace in describe type, but since we haven't specified a namespace, calls will get an error 1006 'is not..'

TypeError: Error #1006: s_introspectable is not a function.
at Test::Test_DescribeType()[C:\DATA_SYNC\CodeProjects\Flash Work\as3 - introspection\Test;Test;DescribeType.as:28]
at [execute-queued]

Uncommenting the line

use namespace introspectable;

and running again allows the function to call successfully:

Test_DescribeType

variable name="introVar" type="Function" uri="com.troyworks.cogs"

method name="s_introspectable" declaredBy="Introspectable::IntrospectableObj" returnType="void" uri="com.troyworks.cogs"

Hello World from introspectable::s_introspectable

Which is the desired result of custom namespaced items that can be introspected and called but not without specifying the namespace up front.