Playchilla logo

AS3 and constants

As3 is lacking a powerful const keyword, this post will show a few tricks to simulate const. Anyone who has worked with C++ has encountered the keyword ‘const’. This can be very confusing at first, but once you get a hang of it you will understand how powerful it’s, and have trouble living without it.

Const will save you


In short, const is about making sure that stuff that shouldn’t change really doesn’t change. Many programmers (and languages for that sake), thinks this is up to the programmer, ‘if you don’t want something to change – don’t change it’. This may work in some cases when a single developer is working on a limited project, however when systems gets more complex and when someone else starts playing with the code or you simply forget – the risk is that that stuff that shouldn’t change get changed resulting in unexpected runtime bugs. Psychologically stuff that is constant make people more secure and less stressed whether it is a constant income, home, breakfast or love. I also think this holds true for programming, being able to trust that something that shouldn’t change really doesn’t.

Correctly enforced constraints are good and will save you and your team from future hassle. Also remember that mr. compiler likes formalism, in fact so much that in some cases it will give you back performance as a token of appreciation.

C++ and const

As far as I know, C++ has the most powerful const declaration, and it’s hard to understand in the beginning, consider the following method:

const Item * const doSomething(const Item& item) const;

This basically says:
1) doSomething takes a reference to a const Item object – it guarantees to not change the item by only calling const methods on it.
2) doSomething is const (last const) – it guarantees will not alter its own object.
3) doSomething returns a constant pointer to an Item that is constant – making sure that it isn’t mutated by the caller.

Any breach of these will result in a compiler error. And we like compiler errors, hrrm, well – at least a lot more than intricate runtime errors.

AS3 and const

In AS3 the keyword ‘const’ exists but its power is very limited in comparison to C++. In ActionScript ‘const’ basically allows you to declare primitives and references as constants, but you can’t lock down entire objects or methods.

To demonstrate, consider the following class member:

private const _position:Vec2 = new Vec2(100, 100);
...
_position = new Vec2(123, 123); // Not ok, compiler error</span>
_position.addX(x); // Ok, only reference is constant

Let me give a simple example of when it would like to use const in AS3. Imagine that you have a class, Shape, with a position and a method to access it.

public class Shape
{
  public function getPos():Vec2 { return _pos; }
  private const _pos:Vec2 = new Vec2;
}

As you are aware of this return a reference to the _pos object, this makes it very easy to make misstakes. Imagine a render method, where we want to render a text to the right of a shape:

public function render(shape:Shape):void
{
  const shapePos:Vec2 = shape.getPos();
  showText(shapePos.addX(50), "Text to the right of shape... or?");
}

Of course this moves the Shape 50 pixels right which was not the intention. Now how can we make sure that this doesn’t happen?

External clone

One solution is to clone the position that is returned – making sure that we don’t alter the original.

const shapePos:Vec2 = shape.getPos().clone();

The disadvantage is of course that we need to remember to do this – so it doesn’t really solve the problem. We want the compiler to say “Hey you are not allowed to modify a shape position from a render method!”

Internal clone

Another solution is to always clone it when it’s returned:

public function getPos():Vec2 { return _pos.clone(); }

This ensures that internal object is not altered, but it seems overkill and performance unwise to always clone it as we sometimes actually read from it.

Interface read only members

Better off, we could create an interfaces that specifies read only members of the actual Vec2 class.

public interface IVec2Const
{
  function getX():Number;
}
public class Vec2 implements IVec2Const
{
  public function getX():Number {return _x; }         // From read only interface
  public function addX(x:Number):void { _x += x; }
}

Then in Shape we can return only the parts we wish to expose:

public class Shape
{
  public function getPos():IVec2Const { return _pos; }
  private const _pos:Vec2 = new Vec2;
}

We could also create a IShapeConst interface that Shape implements – and pass it to the renderer as we don’t want it to modify a shape – only render it.

Read only by inheritance

Finally I just want to mention that it’s possible to do this by inheritance as well:

public class Vec2Const
{
  public function getX():Number { return _x; }
}
public class Vec2 extends Vec2Const
{
  public function addX(x:Number):void { _x += x; }
}
public class Shape
{
  public function getPos():Vec2Const { return _pos; }
  private const _pos:Vec2 = new Vec2;
}

Conclusion

For classes that I use frequently, such as Vec2 I have started to create const interfaces that specifies all const methods. Then whenever something shouldn’t change object are passed by their const interface. Any thoughts on that?

In terms of performance AS3 (measured with flash 10) doesn’t care if methods are called via interface, directly or in a subclass.

1 Comment

    […] I mentioned earlier in my post AS3 and constants AS3 is missing such a feature. Another feature it’s missing is operator overloading (ability […]