Function Overloading in AS3

Why doesn't AS3 have function overloading

If there is anything I hate more than when actionscript doesn't do something I wish it would, it is when people complain about something they wish it would do. Sure, it would be nice if it incorporated every programming concept ever but that just isn't going to happen. In fact, this point is the same for every language out there. It sure would be nice if they all did everything but then there would only be syntacticular differences and that would be silly. Anyway, actionscript does not natively offer function overloading, and I've heard and/or read people complain about that from time to time.

Roll your own

Usually the reason you wish a solution existed natively is because you've used it before and you'd like to have the same ease writing the code. At least, if we follow the premise of not pre-optimizing code. So, if a language doesn't have that construct what do you do? Either find an alternate or roll your own. Today we are going to roll our own method for overloading functions in AS3 to allow for some of the benifits of native function overloading.

This isn't my idea

I have to admit, this isn't my idea. Back in the days of AS2, there was one library that did a lot of rolling its own solutions to constructs actionscript didn't provide. That library was as2lib by Simon Wacker and Martin Heidegger. I remember just reading the as2lib source code to learn different ways of doing thing. They had a solution for function overloading that I used as a basis for the AS3 code. I figured, AS3 had better reflection and introspection (as2lib had libraries for that as well) than AS2 so this should be fairly easy. In some ways it was and in some was it wasn't. That's a good thing because I learned a few things along the way.

Enough typing, where's the code

The code I wrote to allow this functionality is available at github. Usual rules apply, this code is just a proof of concept, for educational purposes only. Though I've written some tests, I make no guarantees.

Sample Usage

Sample usage is available in the Main.as file on github but I'll provide you with a taste here.

private function aFunction(... args):* {
    const overloader:Overloader = new Overloader();
    overloader.addHandler([String, Number], onStringNumber);
    overloader.addHandler([String], onString);
    overloader.addHandler([Number], onNumber);
    overloader.addHandler([int], onInt);
    overloader.addHandler([uint], onUint);
    overloader.addHandler([Boolean], onBoolean);
    return overloader.process(args);
}

private function onInt(value:int):void {
    trace("We got int: " + value);
}

private function onUint(value:uint):void {
    trace("We got uint: " + value);
}

private function onBoolean(value:Boolean):void {
    trace("We got Boolean: " + value);
}

private function onNumber(num:Number):void {
    trace("We got number: " + num);
}

private function onString(str:String):void {
    trace("We got string: " + str);
}

private function onStringNumber(str:String, num:Number):void {
    trace("We got string, number: " + str + ", " + num);
}

// then to use the overloaded function
public funciton Main(){
    aFunction("Hello World", 13); // output: We got string, number: Hello World, 13
    aFunction(1 == 0); // output: We got Boolean: false
    aFunction(13); // output: We got uint: 13
    aFunction("Goodbye"); // output: We got string: Goodbye
}

A couple notes and gotchas that you might be wondering about as you look at this code.

  • Numerical arguments are automatically converted to any numerical class asked for, as long as the value can be of that type.

    • For this reason I made it test numerical explicitness in the following order: uint before int and int before Number.

      • Therefore if their are two matching functions due to numerical parameters a method using uint will be considered more explicit than a method using int or number.
    • You can't force a numerical type. I tried several methods and none worked.
  • If your overloaded function returns void you will need it to return * so it will compile without error.
    • EDIT: not true, just don't use a return statement
  • Because AS3 uses method closures most of the time, instead of anonymous functions, you usually don't have to worry about function scope. This is mostly a good thing. Watch out if you do use an anonymous function though. It will most likely work correct but there are a few ways it could fool you.
  • I wanted to do introspection on the method signatures so you didn't have to send in the values but, alas, method signatures do not seem to be available via reflection. From what I could figure out from studying the Tamarin code, they are part of the functions Trait object which isn't available from actionscript (and may go away in the future according to the documentation). This means you have to put them in as Arrays.

Not True Overloading

Okay, so this isn't true overloading but it gets us a little of the way there. The only solutions available online use the ellipsis (...) method but you still have to write the boilerplate logic to provide type checking. Also, what happens if there is no match? With my code you at least get an error telling you what went wrong. It isn't compile time but it can help with debugging.

Also, look at what this solution actually provides. It doesn't have to be used for function overloading. It could be used anywhere you want to handle differing types of data passed in as arguments. I could envision this helping to trim down some nasty if and/or switch statements. Take a look and see what it could do for you.

Conclusion

I find the Function class and Function objects fascinating in actionscript. Back when I dug into the different types of Delegate classes for AS2 (I actually made a similar one for AS3 at one time) I learned a lot about the language as a whole. Scope used to be the bane of my existence and then I finally understood it. Scope may not be an issue anymore in AS3 but there is still quite a bit to learned about the language from studying Function objects. The very fact that a Function is an object that can be passed around in actionscript is a very nice thing. Not all languages allow that type of functionality. I guess if you are using those, you'll have to roll your own function passing solution.

Under the mask but I didn't ask - Flash Friday

Masks in the flash IDE are an interesting thing. You may have noticed that masks created in the IDE are not found in the normal "mask" property found on a movieclip. This is because it isn't a normal mask. The mask is working on a layer instead of on a single DisplayObject. This little quirk causes some interesting behavior that you may never have noticed before. If you have a MovieClip with a mask as a top layer of the timeline there is some strange behavior when you addChild to that MovieClip. The added content gets placed under the mask. Wait! What? The added content gets placed under the mask. You may not have noticed this behavior in the past because you may never have done it, you may not have your item cut off by the mask or you just might not have been able to figure out why you couldn't see your item. However, it is happening. [ad#Google Adsense] Another twist on this phenomenon is that if the mask isn't the top layer but your remove the items that are on the top layer then add a DisplayObject. Well, in that scenario your new DisplayObject is also placed under this "Layer Mask". I found this out today when I had a top layer above a mask that was a TextField. For a localization project I'm working on I had to wrap the field in a wrapper class that then gets added back where the textfield was. I was trying to figure out why the textfield was now appearing like it was under the mask. The answer...because it now was.

So how did I deal with this? How can you deal with this if you find it happening? First off, it might be an easy thing to just restructure your timeline so the mask isn't on top. If that isn't possible, the hack easy fix is to add a blank MovieClip symbol to the layer above the mask layer. That is what I did for this asset and all is well.

I haven't extensively tested this but my guess is the quirk may exist if you add something to any layer right above a "Layer Mask" it will placed under the mask. Is this something you have experienced? How have you worked around it? Have you used it for any type of effect?

I don't believe you really want to count on this behavior for anything as I don't believe I've seen it documented anywhere. Someone at Adobe might read my blog :) and decide this isn't appropriate behavior they might fix it in Flash Player 20 or something.

Flash Friday Refactored - IS_IN

A while back I wrote a proof of concept isIn functionality injector that seemed to work fairly decently. I even wrote some tests for it that it passed with flying colors. Being a proof of concept I never really used it and never ran into the danger of using that functionality. Recently I downloaded the trial for FDT and since it doesn't have the same type of FlexUnit integration that FlashBuilder 4 has I had to get my tests working differently. When I got the tests up an running my tests for the isIn functionality blew up in spectacular fashion. They didn't just fail, the took the whole unit test display down with them. This was the same class and tests that passed cleanly before. What happened?

It turns out messing with the prototype of Object to solve a problem is like fighting fire with a nuclear explosion. It will probably work but cause serious problems throughout the system. So, following the test driven development methodology of red, green, refactor I saw that it was a time for a refactor. Well that and it was now a red test that I wanted to make green.

I came up with a solution that I think is better. It is more flexible than before, since you can select the class you want to add the functionality to. Even better, you can remove the functionality after you add it. Since I've begun to move my code over to GitHub you can find the new code over at https://github.com/darylducharme/Ducharme-Media-Code/tree/master/src/cc/ducharme/utils. The new test class is available at https://github.com/darylducharme/Ducharme-Media-Code/blob/master/test-src/utils/IsInTests.as

You may notice that the last test - dictionaryEnumerationTest()  at this time - is new. This is the test that checks the problem that I found that was not being tested before. If you are writing tests and find a hole in your tests later, it is always recommended to add new tests to keep you from having the same problem in the future.

Hopefully, someone out there can learn from my mistakes on this occasion. Also, the new isIn class and its static functions are a whole lot more useful than what I had written before. Perhaps someone out there can put it to good use.  What do you think?

Yahoo Flex Map Component Part 3 available

Part 3 in my multi part series on building a flex component out of the Yahoo! Maps API is available over at the Flexcoders group.

In part 1 of this series I talked about the reasons why you would want to make a flex component out of something you can do in actionscript. In part 2 I discussed the basics of the component architecture. From that second article you can create a component that works however you still haven't handled most of the reasons to make a component in the first place. In this article I will take care of those issues the issues of data binding, event handling and making it easier for non coders( sometimes called designers or managers :) ) to work with.

AMFPHP $_explicitType understood

I've been using AMFPHP for a while now. Up until recently I have been using dumb objects and simple NetConnections to pass things back and forth between Flex and PHP. Over time, the objects I was passing back and forth got more complex and strong typing of the objects looked like a better way to go, but there was a lot of code that would have to change in my libraries to make it happen so I kept putting it off. ...

Recently, a couple projects I was working on had me take a look at the Cairngorm micro-architecture to help speed up (re)development. After finding some great tutorials on getting starting with Cairngorm I decided it fit the bill for my needs.

Cairngorm would allow me to refactor some basic frameworks I was going to use for these and future projects while allowing for easier customization and modification. The architecture makes use of RemoteObjects to pass data back and forth instead of raw NetConnection objects. Between RemoteObjects and the ValueObject design (anti?)pattern I felt it was time to work on strong typing my variables, specifically the ones traveling from PHP to Flex.

Two important parts to making this work are the RemoteClass meta tag in Flex and the $_explicitType variable in PHP. The RemoteClass meta tag lets your application know the fully qualified name of an alias class on your server. It works the same for AMFPHP, ColdFusion, Java and others. It should look something like this:

package path.to.asClasses
{
  [RemoteClass(alias="path.to.MyAliasClass")]
  public class MyASClass
  {
    public var id:uint;
    public var name:String;
  }
}

My first thought about the $_explicit type variable was that it would be the inverse of the RemoteClass meta tag and point to the actionscript class. With that in mind I wrote something like this:

<?php

class MyAliasClass
{
  var $_explicitType = "path.to.asClasses.MyASClass";

  var $id;
  var $name;

  public function MyAliasClass( ){}
}

?>

Unfortunately, the data that got passed back to Flex was typed as an ObjectProxy object instead of as a MyASClass object as intended. I did all the basic troubleshooting. I made sure everything was spelled the same. I tried to do searches online and got mostly references passing VOs from Flex to PHP and/or Patrick Mineaults opinion that doing so is wasteful. Not many of the search results talked about going from PHP to Flex and those that did just said you needed to use $_explicitType. Unfortunately I can't find the posting again, but I came across a short post that said they had a similar problem and got it to work by changing $_explicitType to a string representing the fully qualified path of the PHP class. He didn't know why it worked, and neither did I, but I tried the following code and class typing occured as expected:

<?php

class MyAliasClass
{
  var $_explicitType = "path.to.MyAliasClass";

  var $id;
  var $name;

  public function MyAliasClass( ){}
}

?>

As usual, I got it working and now I needed to understand why. Not only why did it work but why did they use the term explicit type? It turns out the use of the RemoteClass meta tag takes care of mapping in both directions. When the Flex app encounters an alias object from remoting ( in this case path.to.MyAliasClass ) it knows what AS class is equivalent. As for explicitType, you just have to think about the full notation ( MyAliasClass::_explicitType ). In object oriented languages an object's properties should represent it's state. In this case it represents the explicit type of MyAliasClass. This is required due to the constraints of PHP. PHP is not case sensitive when it comes to class names. Also, PHP doesn't actually use classpaths. When you include a file there is no reference to the directory structure passed along with it. Though one could be derived, it isn't built into AMFPHP natively.

--
Some other good news related to AMFPHP. While looking for answers I see that AMFPHP now has a new lead who is working on getting version 2.0 out and ready to go. Supposedly he already got authentication working again. His name is Wade Arnold from T8Design. This is good news as it once again assured the future of the AMFPHP project.

----
Daryl "Deacon" Ducharme is currently Director of Application Development for the Interactive Agency Provis Media Group, LLC which helps organizations enhance identity, connect with customers and increase productivity.

Creating Modular Applications

A common application type to create is one large application that has many smaller applications in it. With flex builder you can always build a monolithic application that could do that. However, if you ever want to edit, debug or even add more features you are just making modification more difficult. So before Flex 2.0.1 came out I was trying to create the framework for such an application and it took quite some doing to get it to work right. At that time, flex didn't support modular applications directly ( or at least not officially ) and I had to come up with a way that felt very kludgy. When it came time to implement the framework a little while later flex 2.0.1 was out but I still hadn't heard about modules. Now I have and it makes things much easier, especially with a little help from some other info on the web. ...

My application was a simplistic (web)desktop that allows you to open applications. Because Panels and TitleWindows are the most like applications on the normal desktop they were being used along with the PopUpManager. Using Panels in conjunction with PopUpManager allows the dragging of windows and a usable focus management system. This system worked well when the applications were written into the main application but broke down when I loaded an external swf.

To finally make it work ( before I knew about modules ), I had to load in the swf then listen for the creationComplete event of my application before I could use it. Then I had to take my application ( based on Panel/TitleWindow ) out of the display list of the SWFLoader object I was using and place it in the display list of my main application. At this point I could then drag the windows and it worked for the most part. However, I had problems with scrollbars and the file size was bigger because of the added overhead of the SystemManager for my application which got thrown away anyway. I also didn't like having to write so much clean up code. It felt like such a waste of resources.

Luckily during the implementation phase, while trying to figure out how to make the scroll bars work, I came across Modules. This seemed like the way to go, less overhead and made to work with the SystemManager it is loaded into directly. At first all I gained was the lower overhead and working scroll bars. I still had the same load - listen - remove - add - cleanup scenario that was quite kludgy. But it worked effectively so I left it at that.

Recently, while reading a flex coders mailing list digest I found a link to a blog posting titled "Popup Dialogs as Modules". It explained how to turn a TitleWindow into a loadable module directly. Following Alex's example I was able to do a little refactoring and clean up my code considerably. Not to mention, it seems to run a bit snappier now ( though I have no benchmarks to prove it ). Unlike some of the comments to his post, I was able to use my modules in their own namespace within my larger project.

The final minor annoyance was debugging. I kept having to copy the debug file and rename it to use debugging on my modules. Then I remembered another posting I came across during my module research. It was entitled "How I Debug with Flex Modules" and this simple fix worked to remove this minor annoyance quite well. All you end up doing is loading the module based on whether or not your main application url has the word debug in it. I went a slightly different route for my case that looked like this:

var modulePath:String = APP_DIRECTORY + this.fileLink;// Check to see if the application is the debug version, and if
// so then use the debug module...
if ( Application( Application.application ).url.indexOf( "debug" ) >= 0 )
{
  var debugFileLink:String = this.fileLink.replace( ".swf", "-debug.swf" );
  modulePath =  APP_DIRECTORY + debugFileLink;
}

I am very excited about using modules in many other ways as well. Some things that I have thought of, as well as read are:

  • More Object Oriented design of large applications, allowing for easier updates and debugging ( I am doing this now )
  • Creating new style sheets loaded at runtime
  • Updating and adding complex algorithms to an application similar to dynamic link libraries
  • Modules as config files for larger apps so deployment is quicker and easier.

----
Daryl "Deacon" Ducharme is currently Director of Application Development for the Interactive Agency Provis Media Group, LLC which helps organizations enhance identity, connect with customers and increase productivity.

Adding a ControlBar via Actionscript

For a project I am working on I was using a panel component that had a controlBar. Throughout the project I used something similar several times I decided to make a component that I could extend. Being a glutton for punishment( in this situation at least ), I decided to do it in actionscript instead of MXML. All of the sudden it became very difficult to figure out how to add a ControlBar component to the bottom of a panel. ...

Once the difficulty became apparent and I could not find any other successes online I had 2 choices to make it work quickly. My first choice would be to revert to using MXML for the basis of the component and embed the necessary actionscript in a script tag. My other choice was to not use a ControlBar at all. I chose the third option, be stubborn and figure it out.

The thought kept running through my head that it must be possible, it is ultimately done through actionscript. I tried several things, starting with adding -keep to my compile options and viewing the generated actionscript. In the end the generated actionscript helped me because a comment in the Panel.createComponentsFromDescriptors function didn't jive with it.

The Panel.createComponentsFromDescriptors comment was:

Restore the original document. Otherwise, when we re-add the child when the Panel is a custom component, the child will use the custom component as the document instead of using the document in which the child was declared.

However, the generated actionscript had this line:

mx_internal::_document = this;

So maybe, the CustomPanel.controlBar.document property should be the CustomPanel object itself. So I added that to my control bar initalization function and it worked.

private function initControlBar( ):void
{
var cBar:ControlBar = new ControlBar();
cBar.enabled = true;
cBar.document = this;

// Add stuff to the ControlBar
...

this.addChild( cBar );
}

Just make sure this is the last child in your custom panel when it gets initialized. The Panel code checks the last child to see if it is a ControlBar during initialization.
----
Daryl "Deacon" Ducharme is currently Director of Application Development for the Interactive Agency Provis Media Group, LLC which helps organizations enhance identity, connect with customers and increase productivity.

Flex Builder in Linux

No, Adobe didn't finally port Flex Builder to the Linux platform. However, I did find a post on how to get Flex Builder working in linux. I followed the post and guess what. It worked! Well, it mostly worked. ...

As stated in the post, MXML design view does not work. But the code completion in MXML and Actionscript work great. As the article says, load it into Eclipse 3.2.2, not the current 3.3 ( Europa ). I first tried it with Europa and it would crash, whenever I would try to make a Flex Project. You also need to make sure you are using the Sun JDK. Since Fedora doesn't use it natively I had to download it and set up the eclipse.ini file with the proper path to the Sun JDK. I also had to use the Sun JRE for getting the charting components installed.

Right now it seems to work well enough. It likes to crash when I compile Flex project MXML files but does okay with a basic actionscript project file. I'll have to try it with a larger actionscript project and see if it chokes, or maybe it is just choking on converting the MXML to actionscript.

Hopefully, Adobe will make a linux version of Flex Builder but until then you have to make it work in ways such as this. Now that they have open sourced Flex 3 ( not builder ), perhaps that will make it easier to have a linux native flex builder or a similar open source project. I know that ASDT is planning on having AS3 support and using the Flex 3 SDK, maybe someone can take what they are doing a bit further and make it work with the MXML and a design view.

Link: A follow up post about Flex Buildr on Linux

Just for fun, I changed the Eclipse splash screen as well :)