Enumerations With Class

 

References:
Prog  ActionScript 3.0 – Enumerations with Classes:
http://livedocs.adobe.com/flex/201/html/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Book_Parts&file=04_OO_Programming_161_07.html

http://www.herrodius.com/blog/87

http://www.barneyb.com/barneyblog/2007/11/02/enums-and-actionscripts-static-initializers/

Environment:
ActionScript 3.0; Flex Builder 3.0 with Flex SDK 3.2

Keywords:
ActionScript 3.0,  Enumerations with Classes, private constructor, singleton, static code block

Enumerations:

ActionScript  3.0 documents suggest the use of  classes with only static constants as a way to create enumerations.

The first approach uses variables of basic types such as String, int, or uint within a class.  In fact, Flash API use this approach, as in the following code, we are told:

public final class PrintJobOrientation
{
    public static const LANDSCAPE:String = "landscape";
    public static const PORTRAIT:String = "portrait";
}

The  second approach involves a separate class with static properties for the enumeration:  Here, each static property is an instance of the class and thus allows improved type checking. The example provided is as follows:

public final class Day
{
    public static const MONDAY:Day = new Day();
    public static const TUESDAY:Day = new Day();
    public static const WEDNESDAY:Day = new Day();
    public static const THURSDAY:Day = new Day();
    public static const FRIDAY:Day = new Day();
    public static const SATURDAY:Day = new Day();
    public static const SUNDAY:Day = new Day();
}

An example usage is as follows:

function getDay():Day
{
    var date:Date = new Date();
    var retDay:Day;
    switch (date.day)
    {
        case 0:
            retDay = Day.MONDAY;
            break;
        case 1:
            retDay = Day.TUESDAY;
            break;
        case 2:
            retDay = Day.WEDNESDAY;
            break;
        case 3:
            retDay = Day.THURSDAY;
            break;
        case 4:
            retDay = Day.FRIDAY;
            break;
        case 5:
            retDay = Day.SATURDAY;
            break;
        case 6:
            retDay = Day.SUNDAY;
            break;
    }
    return retDay;
}

Note that the return type is Day; this is how enhanced type checking comes into play.

Exercise for the Reader: Enhancing the Day Class Sample

Adobe documentation suggests an exercise for the reader: enhance this class by associating an integer with each day, as well as a string representation. Here is my solution:

package
{
    public class MyDay
    {
        private var _dayNum:int;
        private var _dayStr:Array = ["Sun","Mon","Tues","Wednes","Thus","Fri","Satur"];

        public static const SUNDAY:MyDay    = new MyDay(0);
        public static const MONDAY:MyDay    = new MyDay(1);
        public static const TUESDAY:MyDay   = new MyDay(2);
        public static const WEDNESDAY:MyDay = new MyDay(3);
        public static const THURSDAY:MyDay  = new MyDay(4);
        public static const FRIDAY:MyDay    = new MyDay(5);
        public static const SATURDAY:MyDay  = new MyDay(6);
        public function MyDay(dayNum:int)
        {
            _dayNum=dayNum;
        }
        public function get dayNum():int
        {
            return _dayNum;
        }
        public function get dayStr():String
        {
            return _dayStr[_dayNum]+”day”;;
        }
        public function toString():String
        {
            return dayStr;
        }
    }
}
class SingletonEnforcer {}

I had intended to use class  SingletonEnforcer to restrict the use of  MyDay constructor to this package,  since I cannot make the MyDay constructor private; but that leads to TypeError 1115. According to http://www.herrodius.com/blog/87 , it is impossible to call the constructor of the inner class (i.e. SingletonEnforcer) in a static member of the top class. 

The alternative is to use an unnamed  static code block:

private static var _enumsInited:Boolean = false;
//unnamed static code block
{
    _ enumsInited = true;
}

and  then modify the constructor; the final code is as follows:

package
{
    public class MyDay
    {
        private var _dayNum:int;
        private var _dayStr:Array = ["Sun","Mon","Tues","Wednes","Thus","Fri","Satur"];

        public static const SUNDAY:MyDay    = new MyDay(0);
        public static const MONDAY:MyDay    = new MyDay(1);
        public static const TUESDAY:MyDay   = new MyDay(2);
        public static const WEDNESDAY:MyDay = new MyDay(3);
        public static const THURSDAY:MyDay  = new MyDay(4);
        public static const FRIDAY:MyDay    = new MyDay(5);
        public static const SATURDAY:MyDay  = new MyDay(6);
        private static var _enumsInited:Boolean = false;
        //unnamed static code block
        {
            _enumsInited = true;
        }
        public function MyDay(dayNum:int)
        {
            if (_enumsInited)
                throw new Error("[MyDay] The enum is already inited.");

            _dayNum=dayNum;
        }
        public function get dayNum():int
        {
            return _dayNum;
        }
        public function get dayStr():String
        {
            return _dayStr[_dayNum]+”day”;
        }
        public function toString():String
        {
            return dayStr;
        }
    }
}

This works, because the static code is executed after all static members have been set!

From
http://www.barneyb.com/barneyblog/2007/11/02/enums-and-actionscripts-static-initializers/

In a nutshell, a static initializer is kind of like a constructor, but it’s for the class object itself, not instances of the class. It gets invoked during classloading, after all static properties have been set, but the class is turned loose for general consumption.

Here is the code where I exercised the above classes Day and MyDay:

package {
    import flash.display.Sprite;

    public class EnumClassAS3 extends Sprite
    {
        public function EnumClassAS3()
        {
            var dayOfWeek:Day = getDay();
            trace (dayOfWeek);
            //Today is (was) Saturday:
            if (dayOfWeek == Day.SATURDAY) {
                trace("[Day] SATURDAY");
            }
            else {
                trace("[Day] Not SATURDAY");
            }
            var strDay:String;
            switch (dayOfWeek)
            {
                case Day.SATURDAY:
                    strDay="Saturday"
                    break;
                default:
                    strDay="Not Saturday";
                    break;
            }
            trace("[Day] strDay:" + strDay);
            var myDay:MyDay = getMyDay();
            trace("[MyDay] dayNum:"+ myDay.dayNum );
            trace("[MyDay] toString:"+myDay);
            trace("[MyDay] dayStr:"+ myDay.dayStr );
            if (myDay == MyDay.SATURDAY) {
                trace("MyDay is: " +"SATURDAY");
            }
            else {
                trace("MyDay is NOT: " +"SATURDAY");
            }
            var myOtherDay=getMyDay();
            if (myOtherDay == MyDay.SATURDAY)
                trace("MyOtherDay is: " +"SATURDAY");
            if (myOtherDay == myDay)
                trace ("SameDay");
            if (myOtherDay === myDay)
                trace ("SameStrictDay");
            var extraDay:MyDay=new MyDay(8);
        }
        private function getDay():Day
        {
            var date:Date = new Date();
            var retDay:Day;
            switch (date.day)
            {
                case 0:
                    retDay = Day.SUNDAY;
                    break;
                case 1:
                    retDay = Day.MONDAY;
                    break;
                case 2:
                    retDay = Day.TUESDAY;
                    break;
                case 3:
                    retDay = Day.WEDNESDAY;
                    break;
                case 4:
                    retDay = Day.THURSDAY;
                    break;
                case 5:
                    retDay = Day.FRIDAY;
                    break;
                case 6:
                    retDay = Day.SATURDAY;
                    break;
            }
            return retDay;
        }
        private function getMyDay():MyDay
        {
            var date:Date = new Date();
            var retDay:MyDay;
            switch (date.day)
            {
                case 0:
                    retDay = MyDay.SUNDAY;
                    break;
                case 1:
                    retDay = MyDay.MONDAY;
                    break;
                case 2:
                    retDay = MyDay.TUESDAY;
                    break;
                case 3:
                    retDay = MyDay.WEDNESDAY;
                    break;
                case 4:
                    retDay = MyDay.THURSDAY;
                    break;
                case 5:
                    retDay = MyDay.FRIDAY;
                    break;
                case 6:
                    retDay = MyDay.SATURDAY;
                    break;
            }
            return retDay;
        }
    }
}
Advertisement

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 )

Connecting to %s


Follow

Get every new post delivered to your Inbox.