Skip to content

Injecting Methods into HaXe with "using"

May 23, 2009

Nicolas just added a new keyword to the haXe compiler called “using”.  In short, this keyword lets you inject additional methods into instances of types.

“using” explained

The haXe “using” keyword  is a special import command for classes.   The command will import the given class normally.  However, it has special behavior if the imported class has any static functions accepting an argument.

The “using” keyword takes any static functions defined in the class, and adds those static methods to the argument type, as if the argument type defined the method itself.  In this sense, it behaves like a sort of implicit mixin, or trait.  However, it’s also very different from these approaches, and to the best of my knowledge, nothing like this exists in any other language.

Explaining what’s happening in simple prose is actually a bit cumbersome, so here’s some example code.  First, we’ll give a simple haXe example without “using”.  The first class is a Demo class that contains the main function:

// in Demo.hx
class Demo{

public static function main(): Void
{
trace(BarStringClass.addBar('foo'));
}

}

The second is a class that contains additional methods:

//in BarStringClass.hx
class BarStringClass{
public static function addBar(str:String) :String
{
return str + ' bar';
}
}

If we compile the code using main() from Demo, we’ll get “foo bar”.  We’re simply using the static class from BarStringClass to process the string and tracing it.  Pretty simple.

Now let’s look at what we can do to Demo.hx with “using”.  We’ll use the same BarStringClass from before, but we’ll change Demo slightly:

//in Demo.hx
using BarStringClass; // here's the 'using' keyword in use
class Demo{

public static function main(): Void
{
trace('foo'.addBar());
}

}

haXe now lets us access BarStringClass static functions as if they were functions of the String class.  In this fashion, the standard base classes can be augmented with additional methods without the need to extend them explicitly.

Notice how in this example it wasn’t even necessary to specify the “str:String” argument required by addBar(). When the haXe compiler injects the methods from BarStringClass, it will automatically fill in the current instance as the first argument… turning BarStringClass.addBar(‘foo’) into ‘foo’.addBar().  All of the first argument Types of the “using” classes will be augmented in this way.

So in this case, BarStringClass had one static function (addBar), and the first argument type was String.  Therefore, every String instance now gets the addBar() function.  You could have many different Static functions in a “using” class, and each of the first argument classes will get injected in the same way.

“using” with types and/or classes

The other nice thing about this approach is that it works with the more broadly defined Types/typedefs, and not just Classes. So, my IterTools functions that work (mainly) with Iterable Types can be injected with “using”, and then you can do things like:

for ( i in [1,2,3,4].cycle(5) ){
trace(i);
}

…to iterate through the numbers 1 through 4 five times. “cycle()” and the rest of the functions that operate on Iterables would also then work with Lists, FastLists, Hashes, and so forth.  When you add “using IterTools;” at the top of a class file, anything that can iterate can now “cycle()”.

Caveats

There are two significant caveats with “using”.  The first is that the injected methods are not available through reflection.  This means they’re not part of the “run-time” class instance.  The second caveat is that it can be very easy to overload several instances of a single method name (from multiple “using” classes).  Currently, haXe’s behavior is to only use the first matching static method from a “using” class.

“using” can be habit forming

Some of the positives to the “using” keyword approach are:

  1. You can manage classes externally from code that defines them, seamlessly adding in functionality by augmenting classes and typedefs.
  2. Anything you can do through the “using” keyword can be done by using static classes, so there is very little ‘magic’ going on… just some clever reformatting of function calls.
  3. There’s a ton of static classes out there (in addition to my own) that already contain a lot of good practical functionality.  You can easily reuse these classes as “using” classes, or write your own that handle specific needs.
  4. Method completion works with –display.  So once you include the “using” keyword with an appropriate class, you can instantly see the extra available methods by triggering a code-completion request inside your editor (assuming the editor does –display code completion).

I’m assuming “using” will be added in the next version of haXe (2.04).  Till then, you can play around with it by downloading and building from the CVS sources.

7/26 Update: “using” is now officially part of haXe (2.04).

From → haXe

5 Comments
  1. Pimm Hogeling permalink

    It has been added in 2.04, available for download now haXe.org.

  2. Appears to be equivalent to “extension methods” in C#

Trackbacks & Pingbacks

  1. haXe 2.04 released !
  2. Using jQuery in haXe | Andy Li's Blog
  3. Method chaining, Haxe ‘using’, and PBE/Hydrax components | Dion Amago

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

%d bloggers like this: