Enums Class

Matt Karl edited this page May 15, 2015 · 1 revision

Oracle's article on Java enums defines an enum type as a "special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it."

A simple example might be compass directions (NORTH, SOUTH, etc):

// standard convention for naming seems to be CAPS for values
// (as they are constants) and an initial-cap for the enum itself
var Direction = new springroll.Enum(
    "NORTH", 
    "SOUTH", 
    "EAST", 
    "WEST"
);

Enums help make code more readable and less-error prone. For instance, say you have a game where characters move along a grid using the function

/**
 * Move character 1 space along specified axis
 * @param {Int} direction
 */
moveCharacter = function(direction)
{
    switch (direction)
    {
        case 0:
            this.y -= 1;
            break;
        case 1:
            this.y += 1;
            break;
        case 2:
            this.x += 1;
            break;
        case 3:
            this.x -= 1;
            break;
    }
};

Every time moveCharacter() is invoked, it will need a value of 0-3.

When "Programmer-A" wrote the function, they figured an order of 0-3 = North, South, East, West made sense because North and South are both Y axis, and the East/West are X direction.

However, "Programmer-B" remembers the cardinal directions with the mnemonic "never eat soggy waffles" and assumes the order as 0 = North (y axis), 1 = East (x axis), and finds their character does move as expected! #wonky #uh-oh

/**
 * Move character 1 space along specified axis
 * @param {enum.Direction} direction
 */
moveCharacter = function(direction)
{
    switch (direction)
    {
        case Direction.NORTH:
            this.y -= 1;
            break;
        case Direction.SOUTH:
            this.y += 1;
            break;
        case Direction.EAST:
            this.x += 1;
            break;
        case Direction.WEST
        this.x -= 1;
        break;
    }
};    
// With ints, the code goes South according to Programer-A's code, 
// but East according to Programer-B's mind/mnemonic,
// and when Programer-C has to edit the code during bug testing,
// they won't have any idea what direction the character is going 
// (or even, if it IS a direction? Is 1 the amount of spaces? Is
// 1 the ID for the character in a array?)
moveCharacter(1);

// Using an Enum value, Both A and B programers send the 
// character in the direction they intended, and Programer-C 
// doesn't have to guess the meaning, value, and is given the hint
// that they could use .NORTH, .SOUTH, etc. to fix the bug. 
moveCharacter(Direction.EAST);

##Stringly Typed Savior Enums also solve "stringly" typed variables.

The code could be written as moveCharacter("east"), but that is cumbersome for many reasons, including:

  • typos (eg "est")
  • case errors (eg "East")

An enum, Direction.EST will let you know the value is incorrect ''right-away'', as it would when someone attempts Direction.NORTH_WEST!

##Console/Debugging Advantage One other thing that makes enums great, is that they print out the string value when logged, so if you're trouble shooting the moveCharacter function...

moveCharacter = function(direction)
{
    Debug.log('moving character ' + direction);
    // output = "moving character NORTH", 
    // which is much more useful than "moving character 0"!
    switch (direction)
    {
        //...

##A few notes on Springroll's implementation You can specify an initial value to increment-from like so, thus creating a 1-4 Enum for Directions:

var Direction = new springroll.Enum(
   {
       name: "NORTH",
       value: 1
   }
   "SOUTH", // value of 2
   "EAST", // value of 3
   "WEST"
);

You can also enter values for every item. Say you wanted to accept both moveCharacter(Direction.NORTH) and moveCharacter(Direction.UP), you could define the Enum as:

var Direction = new springroll.Enum(
{
    name: "NORTH",
    value: 1
},
{
    name:"UP",
    value: 1
}
{
    name:"SOUTH",
    value: 2
},
{
    name:"DOWN",
    value: 2
});