Jun 19
Mixins in ActionScript 3
In a previous post I discussed how you can use the include statement to ‘mixin’ methods and properties defined in an ActionScript file into your classes. I find this approach to be somewhat limited, so I’ve put together a class that allows you to mix one class into another. The class is an all-static class that is simply called Mixin. The class is a bit long to include in this post, but you can view the source by clicking here.
Here is a quick example of how you can use this class. Let’s start with two classes that we will use as mixins:
public dynamic class ClassMixin { import flash.utils.*; // bound method that retains reference to this class // this will always return the fully qualified path // to this class public function whoAmI () : String { return getQualifiedClassName(this); } // function expression that is attached to the prototype // this return the class name of the class that it is // called from prototype.whoBeMe = function () : String { return getQualifiedClassName(this); }; // this will return the class object for the instance // that invokes it prototype.myClass = function () : Class { return getDefinitionByName(this.whoBeMe()) as Class; }; }
public class Ext { public static var staticVar : Number = 123; public var instanceVar : Number = 321; public static function staticMethod () : String { return 'I am static'; } public function instanceMethod () : String { return 'I am an instance'; } public function iCallProtected () : String { return iAmProtected(); } protected function iAmProtected () : String { return 'Protected'; } }
And a third class that is the mixee (the one that we will mix the other two classes into).
public dynamic class Model { // dynamic reference to 'this' class object. private static var self : Class = prototype.constructor; // mixin classes during static init Mixin.extendClass(self, ClassMixin); Mixin.extendClass(self, Ext); public function Model() { } }
In the Model class above you will see two calls to Mixin.extendClass(). The extendClass method takes the class in the second argument and mixes its methods and properties (both static and instance) in to the class in the first argument. These extendClass method calls are made directly inside the class block, so they are invoked when the Model class object is initialized. You can read more about this in my previous post about static initializations in ActionScript.
So, now if you were to execute the following class:
public class Main extends Sprite { public function Main() { var m : Model = new Model(); //bound method returns original class name trace (m.whoAmI()); // this function is not bound and it returns name // of the class that is calling the function trace (m.whoBeMe()); trace(m.myClass()); //mixed in from Ext trace (Model['staticMethod']()); trace (m.instanceMethod()); trace(m.myClass().staticVar); trace(m.instanceVar); // mixed in method calls a protected method in the Ext class trace (m.iCallProtected()); // you can override methods that are attached to prototype at runtime Model.prototype.whoBeMe = function () : String { return 'I am you'; }; trace (m.whoBeMe()); } }
You would see the following in the console:
com.rxr.mixinexample::ClassMixin
com.rxr.mixinexample::Model
[class Model]
I am static
I am an instance
123
321
Protected
I am you
You can view the full source and download it here.

July 9th, 2007 at 4:37 am
This is really cool, albeit a bit awkward to work with over composition since you can’t really pick up problems or compatibility issues prior to runtime.
The main thing I’m trying to sort out is how you would get this to work in a slightly more controlled way, at very least not requiring the recipient Class of the mixin to be dynamic.
I tried pre-declaring all the methods of the mixin on the recipient (i.e.: public var addEventListener:Function in the static initialization) but it would still produce an error when I’d try to perform the mixin on a non-dynamic recipient Class.
Another potential hazard here is incompatible overrides. If ClassB is being mixed in to ClassA, and both have a method called ’sayHello’ with an incompatible signature issues could arise. For example:
dynamic class ClassA
{
function sayHello(to:String):void {};
}
class ClassB
{
function sayHello(id:int):Boolean {};
}
ClassA mixes in ClassB into itself… ClassB’s ’sayHello’ would override ClassA’s ’sayHello’, but the developer would not be aware of this until runtime or when things break down. And the IDE will be showing them ClassA’s original ’sayHello’ signature and spitting about incompatibles if they try to (knowingly) call it using ClassB’s arguments/return.
All the same pretty cool application of mixin…
July 9th, 2007 at 11:03 pm
I digress a bit it appears the mixin methods do not override the source methods… at least not in this implementation. The source methods override the mixin methods, which is a little antithetical to normal class Extends (if you are using a method called ‘extendClass’, would expect a similar behavior, etc.).
The util method could be fitted with a switch or rules to determine override characteristics, like MetaObject Protocol/AOP sort of stuff.
July 10th, 2007 at 2:38 am
Hi alinear,
Thank you for the comment. Just to be clear on what’s going on here. There are three objects that we are dealing with: the static class object, the traits object, and the prototype object.
When you declare a method inside a class like so,
dynamic class ClassC
{
function sayHello(to:String):void {};
}
it is a bound method that is attached to the traits object.
when you declare method like this,
dynamic class classD
{
prototype.sayHello = function () : void {};
}
it is attached to the prototype.
Both the traits and the prototype are shared by all instances of a class. The difference between the two is that you cannot add methods to the traits object at runtime, nor can you override existing methods, but you can do both with the prototype.
So, in the Mixin class when methods are copied from one class to another they are added to the prototype of the recipient class.
In your example above, when the sayHello method from ClassB is mixed into ClassA it gets added to the prototype on ClassA. It does not override the existing sayHello method on ClassA because that method is on the traits object (and, as I mentioned above, you cannot override this method at runtime anyway). Now ClassA has two sayHello methods. When you call a method on a class instance, AS3 first checks the traits object, then if the method is not found it will check the prototype (and then parent classes prototype, and on up the prototype chain). So, if you call new ClassA().sayHello() you would get the sayHello method that was declared in the ClassA definition, but if you call ClassA.prototype.sayHello() you would get the method that was mixed in from ClassB.
Derek
August 17th, 2007 at 4:53 pm
Hey Derek,
Great stuff! One problem I ran into is when dealing with mixin properties that need to be bindable. Have you ran into this and found a solution?
Thanks,
TommyB
October 8th, 2007 at 3:14 pm
This is great! Thanks for the info!
On issue, as I’m sure you are aware, is that function expressions in AS3 don’t work well as event listeners. Snippet from Adobe’s ‘Programming Actionscript 3.0′ (pg 361) (http://www.adobe.com/go/programmingAS3_pdf):
————-
When you pass in a dynamic property name as an argument to addEventListener(), Flash Player is unable to create a bound method. This is because what you are passing as the listener parameter is nothing more than the memory address of your listener function, and Flash Player has no way to link that memory address with the myListenerObj instance.
————-
Thus, when you create a mixin function like this:
prototype.test = function(event:Event):void
{
trace(”the this keyword refers to: ” + this);
}
The trace says “the this keyword refers to: [object global]” when the function is called as an event listener. Furthermore, if you instead define the function using “public function test…” then ‘this’ is of course bound to the single instance of the Mixin object.
Any ideas on how one might get around these limitations so that Mixin methods could be used as event listeners?
November 21st, 2007 at 6:31 pm
FYI, I figured out the solution to my own problem. Solution was to resurrect the old ‘Delegate.create’ functionality that was apparently dropped in ActionScript 3. I implemented code very much like PrototypeJS.com’s ‘bind’ code. Details on my blog here
(http://jordan.broughs.net/archives/2007/11/resurrecting-actionscripts-delegate-for-function-binding-in-as3)
February 12th, 2008 at 5:14 pm
Very cool concept. After dissecting the code, I started to wonder if it was possible to mix accessors (getters and setters). Unfortunately, I couldn’t get the setter to cooperate, but the getter seemed to work just fine. Do you know if it’s even possible to add a setter? Thanks.
February 13th, 2008 at 9:32 pm
Hey Todd –
No, I do not think that it is going to be possible to mix in a setter since there is no way (that I know of) to access the underlying function object. For most cases, I don’t think you’d want to mix in getter/setters anyway since they usually reference private variables.
April 10th, 2008 at 3:31 pm
Hi Derek,
I was looking for something else and found your mixin example.
Would it be anyhow possible to get a name of a class that called a method of another class?
public class Main extends Sprite
{
public function Main()
{
var m:Model = new Model();
}
}
public class Model
{
public function Model()
{
trace(”How do I know that I was called by Main?”);
trace(arguments.callee + ” doesn’t work.”);
}
}
I’d be very grateful for any clues.
April 11th, 2008 at 2:18 pm
@ Og2T –
You may want to check out this post by Doug McCune: http://dougmccune.com/blog/2008/02/21/sneaky-flex-trick-to-get-the-name-of-any-calling-functions/
September 19th, 2008 at 4:21 am
[...] Wischusen: Mixins in ActionScript 3 (perhaps going too far) | [...]
March 30th, 2009 at 6:35 am
I downloaded the example and modified it a bit. and i expirience one problem. if to modify a var inside the class like this
package com.rxr.mixinexample
{
public class Ext
{
public var txt:String = “initial text”;
public function settxt () : void
{
this.txt = “modified text”;
}
}
}
and try to get in from Main
public function Main()
{
var m : Model = new Model();
trace(m.txt);
m.settxt();
trace(m.txt);
}
you stil got the initial value.
initial text
initial text
WHY?
March 31st, 2009 at 5:59 am
While playing a bit with code I did understand the reason why it happens. But it ruins mixin approach as alternative to C++ like multiple inheritance. If to have method that return this in for example Ext class
public function getMe():Ext{ return this; }
you can reach the txt var from Main like that
var m : Model = new Model();
var e : Ext = m.getMe();
trace(e.txt);
Another workaround is to have getVar method for every var in a class. But still m.txt outside the Ext class is not the same var that this.txt inside Ext.