From JavaLostEnumeratedTypes :
Enumerated types are vitally important. You want to declare several unique values in the same namespace, and you want to do this efficiently (i.e not with strings). In C, with the enum keyword, the compiler manages this for you. Many SQL databases have sequenced values. With Java, you leave this to the maintenance programmer to get correct. Furthermore, since you never want to duplicate information, enums also allow you to declare arrays of the right size automagically:
enum quux { foo, bar, baz, NUMBER_OF_QUUX }; fred quuxen[NUMBER_OF_QUUX]; quuxen[foo] = fred('barney');This approach breaks type safety. NUMBER_OF_QUUX is not a valid element of quux but can be assigned to a variable of type quux. Better would be to use ModulaTwo's approach and provide language support for getting the values of the first and last elements and number of elements in an enumeration.
The model for good enumerated types is not C/C++, but the Modula family of languages (ModulaTwo, ModulaThree, OberonLanguage). With proper ordinal types (including integers and cardinals), you can do useful things like:
FOR FIRST(anOrdinal) TO LAST(anOrdinal) DOwhich guarantees that you've covered exactly the possible values. You can also do static checking on CASE statements so you get told if the range has changed and your code now misses a case (yes, I know SwitchStatementsAreEvil, but sometimes they make sense). It gets cute, and self-describing, when you can define ranges, such as:
TYPE LowerCase = ['a'..'z'];The next trick is that the compiler can exploit this to avoid run-time checking because it knows statically that array access for types such as:
TYPE CharacterArray? = ARRAY LowerCase OF SomethingOrOther?;will always be within range.
This is completely wrong. (Big smiles ;) An enumerated type is an efficient way of creating symbols, ala Smalltalk's #symbols, and they are also an efficient way of creating maps, as in quuxen[foo] above. Intervals and range splices are useful, but they aren't what enums are good for. Enums are for improving the readability of the code, and for compile-time operations. Intervals and range splices are run-time objects. So, the model for enums is Perl's AutoVivification and Perl's hashes. -- SunirShah
Someone edited away some of the rest of the original post. How about, in the same vein,
TYPE Quux = [Foo, Bar, Baz];which still gives you
TYPE Quuxen = ARRAY Quux OF Thingumies;which can be accessed by:
quuxen[Quux.Foo] = aThingumy;The slice stuff is sugar to avoid having to type out large ranges. If you're going for static typing, then let's expoit it and have some static slices as well, and let the type system document your intentions.
See also: EnumeratingTrueAndFalse