Enum base class that does most of the right things.

(The beginning.)


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@5351 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2008-09-04 01:22:14 +00:00
parent f22aab43ce
commit 85a5cc1de1
+165
View File
@@ -0,0 +1,165 @@
//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2007 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.util {
import flash.utils.Dictionary;
/**
* Base enum class for actionscript. Works pretty much like enums in Java, only you've got
* to do one or two things
*
* To use, you'll want to subclass and have something like the following:
*
* public final class Foo extends Enum
* {
* public static const ONE = new Foo("ONE");
* public static const TWO = new Foo("TWO");
* finishedEnumerating(Foo);
*
* // {at}private
* public function Foo (name :String)
* {
* super(name);
* }
*
* public static function values () :Array
* {
* return Enum.values(Foo);
* }
* }
*/
public class Enum
implements Hashable, Comparable
{
/**
* Call this constructor in your enum subclass constructor.
*/
public function Enum (name :String)
{
const clazz :Class = ClassUtil.getClass(this);
if (Boolean(_blocked[clazz])) {
throw new Error("You may not just construct an enum!");
}
var list :Array = _enums[clazz] as Array;
if (list == null) {
list = [];
_enums[clazz] = list;
}
list.push(this);
// now, actually construct
_name = name;
}
/**
* Get the name of this enum.
*/
public function name () :String
{
return _name;
}
/**
* Get the ordinal of this enum.
*/
public function ordinal () :int
{
return (_enums[ClassUtil.getClass(this)] as Array).indexOf(this);
}
// from Hashable
public function equals (other :Object) :Boolean
{
// enums are singleton
return (other === this);
}
// from Hashable
public function hashCode () :int
{
return ordinal();
}
/**
* Return the String representation of this enum.
*/
public function toString () :String
{
return _name;
}
// from Comparable
public function compareTo (other :Object) :int
{
if (!ClassUtil.isSameClass(this, other)) {
throw new ArgumentError("Not same class");
}
return Integer.compare(this.ordinal(), Enum(other).ordinal());
}
/**
* Turn a String name into an Enum constant.
*/
public static function valueOf (clazz :Class, name :String) :Enum
{
for each (var enum :Enum in values(clazz)) {
if (enum.name() === name) {
return enum;
}
}
throw new ArgumentError("No such enum [class=" + clazz + ", name=" + name + "].");
}
/**
* Get all the enums of the specified class, or null if it's not an enum.
*/
public static function values (clazz :Class) :Array
{
var arr :Array = _enums[clazz] as Array;
if (arr == null) {
throw new ArgumentError("Not an enum [class=" + clazz + "].");
}
return arr;
}
/**
* This should be called by your enum subclass after you've finished enumating the enum
* constants. See the example in the class header documentation.
*/
protected static function finishedEnumerating (clazz :Class) :void
{
_blocked[clazz] = true;
}
/** The String name of this enum value. */
protected var _name :String;
/** An array of enums for each enum class. */
protected static const _enums :Dictionary = new Dictionary(true);
/** Is further instantiation of enum constants for a class allowed? */
protected static const _blocked :Dictionary = new Dictionary(true);
finishedEnumerating(Enum); // do not allow any enums in this base class
}
}