PROPOSAL: Abstract enums (version 2)

Joe Darcy Joe.Darcy at Sun.COM
Wed May 6 14:55:05 PDT 2009


Hello.

A few general comments and then some specifics.

My general limited sympathy for this approach continues.  For example, 
in the motivating example, the real enum types and enum constants could 
be defined to return TableEnumGuts objects (perhaps with type 
parameters) rather than delegating internally.  For correctness, the 
TableEnumGuts objects should be immutable, etc.

On the the specifics, as Bruce has pointed out, there is no 
"@AbstractEnum" annotation or class file attributes to mark enum types.  
There is an ACC_ENUM class modifier bit used for that purpose.  However, 
today there are situations where the class file is marked with ACC_ENUM 
and the class file is marked abstract; this occurs when an enum type 
declares an abstract method and each enum constant is implemented with a 
specialized enum constant class that implements the method.  The 
compiler checks that these structural correctness conditions are 
satisfied and that "abstract" is *not* applied in source to the enum 
type even though an abstract class results.

Enum types have strong instance control; instances can only be created 
in the class itself (currently all constructors are implicitly private) 
and there are safeguards in the platform to prevent rogue enum instances 
being created via core reflection (setting accessible and calling a 
private enum constructor), cloning, and serialization.  For example, 
core reflection checks the ACC_ENUM bit to prevent both constructors on 
enum types and the constructor of an anonymous classes implementing a 
specialized enum constant from being called reflectively.  See 
java.lang.reflect.Constructor:

     536         if ((clazz.getModifiers() & Modifier.ENUM) != 0)
     537             throw new IllegalArgumentException("Cannot 
reflectively create enum objects");
     538         if (constructorAccessor == null) 
acquireConstructorAccessor();
     539         return (T) constructorAccessor.newInstance(initargs);

http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/6c7c0bccab55/src/share/classes/java/lang/reflect/Constructor.java 


This proposal would complicate making sure those instance control checks 
were still being enforced in all locations.

-Joe

On 04/30/09 11:20 PM, Derek Foster wrote:
> Per feedback on the Project Coin mailing list, this proposal has been revised to provide more detail about how abstract enums affect serialization, class file format, the 'switch' statement, and 'Class.isEnum()', as well as additional text making more explicit the fact that this proposal is substantially different in both intent and implementation from various "extensible enums" proposals that have been considered and rejected in the past by the enum working group.
>
> AUTHOR: Derek Foster
>
> OVERVIEW
>
> The Java Enumerated type feature is unlike similar features in any other language which preceded it. In prior languages, an enumerated type was simply a collection of integer constants. In contrast, Java's enumerated type is a rich datatype that has more in common with classes than it has with a simple constants. Enumerated types can contain complex data, as well as methods to operate on that data. Individual enumerators may be subclasses of the enumeration class that contains them, and may override methods to provide enumerator-specific behavior.
>
> Unfortunately, there is one striking difference between Java's enumerations and classes that can become a significant inconvenience: While classes allow use of a superclass to hold data and methods which are shared between a variety of subclasses, Java enumerations have no such feature. In particular, every Java enumerated type must explicitly specify all of its data and methods that are not inherited from the base class Enum<T>. If there are a number of enumerations that share related behavior, each enumeration must specify it redundantly. The only way to share behavior between these enumerations is to manually implement use delegation.
>
> Note that the term "abstract enum" is somewhat imprecise, and has historically been interpreted (in particular, by the team responsible for defining how to add enumerated types to Java) to refer to a different concept than the one that is specified by this proposal. Specifically, the "extendable enums" approach, in which an abstract enumerated type which declares enumeration constants could be extended by another enumerated type which declares additional constants. Since there seems to have been some confusion on this point, I wish to specifically point out that the interpretation of the phrase "abstract enum" as it is used in this proposal is quite different from that assumed by the "extensible enums" feature that has been considered (and rejected) in the past. The extensible enums proposal was an attempt to define behavior of concrete subtypes of concrete enumerated types. This proposal, on the other hand, attempts to define the behavior of abstract uninstantiable supertypes of enumerated types. The focus of this proposal is not on adding "interface"-related features to enums -- it is on implementation sharing. As such, it is specifically designed to avoid the implementation and specification problems (difficulty with serialization, switch statements, etc.) that have given the phrase "abstract enums" a bad name in the past.
>
> For instance, imagine a system in which enumerations are used to access columns of tables in a relational database. There might be one enumeration for each table, and the enumerators of each type might represent the columns in that table. Presumably, each enumerator would contain the name of the table, as well as the name of a specific column, and perhaps other metadata, such as access privileges.
>
> It would seem natural to model such a system like this:
>
> enum Access { PUBLIC, PRIVATE };
>
> /** 
>  * This holds the shared definition of what it means
>  * to be a database table column identifier 
>  */
> abstract enum TableColumnDef {
>     // Note: No enum constants are declared here!
>     // This is just a supertype!
>     private String tableName;
>     private String columnName;
>     private Access access;
>     protected TableColumnDef(String tablename, String columnName, Access access) {
>         this.tableName = tableName;
>         this.columnName = columnName;
>         this.access = access;
>     }
>     public String getTableName() {
>         return tableName;
>     }
>     public String getColumnName() {
>         return columnName;
>     }
>     public Access getAccess() {
>         return access;
>     }
>     @Override
>     final String toString() {
>         return tableName + "." + columnName;
>     }
> }
>
> /** A specific table */
> enum PersonTable extends TableColumnDef {
>     NAME_COLUMN("Name", Access.PUBLIC),
>     AGE_COLUMN("Age", Access.PRIVATE),
>     WEIGHT_COLUMN("Weight", ACCESS.PUBLIC);
>     private PersonTable(String columnName, Access access) {
>          super("PersonTable", columnName, access);
>     }
> }
>
> /** Another specific table */
> enum PetTable extends TableColumnDef {
>     PETNAME_COLUMN("PetName", Access.PUBLIC),
>     SPECIES_COLUMN("Species", Access.PUBLIC);
>     private PersonTable(String columnName, Access access) {
>          super("PetTable", columnName, access);
>     }
> }
>
> However, this cannot be done in Java, because inheritance from user-specified abstract types is not supported for enumerated types. (The only abstract type that is considered legal to inherit from is Enum<T>). The closest equivalent in Java as it currently exists is to model the desired system is something like this, using delegation instead of inheritance:
>
> class TableEnumGuts {
>     private String tableName;
>     private String columnName;
>     private Access access;
>     protected DatabaseEnum(String tablename, String columnName, Access access) {
>         this.tableName = tableName;
>         this.columnName = columnName;
>         this.access = access;
>     }
>     public String getTableName() {
>         return tableName;
>     }
>     public String getColumnName() {
>         return columnName;
>     }
>     public Access getAccess() {
>         return access;
>     }
>     @Override
>     final String toString() {
>         return tableName + "." + columnName;
>     }
> }
>
> enum PersonTable {
>     NAME_COLUMN("Name"),
>     AGE_COLUMN("Age"),
>     WEIGHT_COLUMN("Weight");
>     private TableEnumGuts guts;
>     private PersonTable(String columnName, Access access) {
>         guts = new TableEnumGuts("PersonTable", columnName, access);
>     }
>     public String getTableName() {
>         return guts.getTableName();
>     }
>     public String getColumnName() {
>         return guts.getColumnName();
>     }
>     public Access getAccess() {
>         return guts.getAccess();
>     }
>     @Override
>     final String toString() {
>         return guts.toString();
>     }
> }
>
> enum PetTable extends TableEnum {
>     PETNAME_COLUMN("PetName"),
>     SPECIES_COLUMN("Species");
>     private TableEnumGuts guts;
>     private PersonTable(String columnName) {
>         guts = new TableEnumGuts("PersonTable", columnName, access);
>     }
>     public String getTableName() {
>         return guts.getTableName();
>     }
>     public String getColumnName() {
>         return guts.getColumnName();
>     }
>     public Access getAccess() {
>         return guts.getAccess();
>     }
>     @Override
>     final String toString() {
>         return guts.toString();
>     }
> }
>
> Note how much more code (and worst of all, boilerplate duplicate code) is required in the second example, since each enumerated type must provide forwarding methods for each method in the 'TableEnumGuts' class.
>
> In one example that the author of this proposal was forced to deal with, there were 30 such enumerated types which conceptually extended the same base class, each of which had to implement that conceptual inheritance by delegating four or so methods to an internal "guts" object. This meant that any time time the signature of any of those four methods had to be changed, the change had to take place in 30 different forwarding methods as well. In another case (working for a different company) there were 10 such methods, duplicated over four conceptual subclasses, with similar problems.
>
> This proposal attempts to solve the above problem by defining the semantics of abstract enumerated types, and what it means for an enumerated type to have an abstract supertype, so as to allow code similar to the first example to work as expected in a Java compiler.
>
>
> FEATURE SUMMARY:
>
> Defines the meaning of inheritance from abstract supertypes for enumerated types.
>
> Note that this proposal specifically does not allow abstract enumerated types to have enumerators, since the semantics of these create difficult problems with inheritance (and open, in the words of one evaluator to a Sun bug submission, "a can of worms", related to the defunct "extendable enums" idea that has been proposed and rejected in the past.).
>
>
> MAJOR ADVANTAGE:
>
> Eliminates a missing feature between java enumerations and java classes, and restores a feature of the "typesafe enumeration" pattern that is not supported by Java enumerations as they are currently implemented.
>
>
> MAJOR BENEFIT:
>
> Elimination of duplicate code when related enumerated types need to be declared. Allows subclassing within enumeration types. Eases maintenance of families of enumerated types. Makes implementation sharing among related enumerated types work in a familiar manner analogous to how it works with classes.
>
>
> MAJOR DISADVANTAGE:
>
> There will be some work in the compiler necessary to implement this feature.
>
> Some people would like to be able to have concrete enums extend each other ("extensible enums"). This proposal does not attempt to provide such a feature, since it has been determined to be very difficult to specify and implement in the past.
>
>
> ALTERNATIVES:
>
> Note the delegation workaround being used above. This allows subtypes to share code, but results in potentially large numbers of forwarding methods and difficulties with code maintenance.
>
>
> EXAMPLES
>
> SIMPLE EXAMPLE:
>
> abstract enum SuperEnum {
>     // Note: no enum constant declarations allowed here!
>     int getTheAnswerToTheUltimateQuestion() {
>          return 42;
>     }
> }
>
> enum MyEnum extends SuperEnum {
>      MY_ENUMERATOR;
> }
>
> class DeepThought {
>     Object returnTheAnswer() {
>         MyEnum[] values1 = MyEnum.values(); // OK
>         MyEnum values2 = MyEnum.valueOf("MY_ENUMERATOR"); // OK
>         SuperEnum values1 = SuperEnum.values(); // Error: No such method
>         SuperEnum values2 = SuperEnum.valueOf("whatever"); // Error: No such method
>         return MY_ENUMERATOR.getTheAnswerToTheUltimateQuestion();
>     }
> }
>
> ADVANCED EXAMPLE:
>
> abstract enum Base1 {
>     protected final int sharedData;
>     public int getSharedData() {return sharedData;}
>     protected Base1(int sharedData) {
>         this.sharedData = sharedData;
>     }
> }
>
> abstract enum Base2 extends Base1 {
>     protected final int otherSharedData;
>     public int getOtherSharedData() {return sharedData;}
>     protected Base2(int sharedData, int otherSharedData) {
>         super(sharedData);
>         this.otherSharedData = sharedData;
>     }
> }
>
> enum Instances extends Base2 {
>     INSTANCE1(10, 100),
>     INSTANCE2(20, 200),
>     INSTANCE3(30, 300) {
>          public int getSharedData() { return 40; }
>     }
>     private Instances(int sharedData, int otherSharedData) {
>         super(sharedData, otherSharedData);
>     }
> }
>
> class AClient {
>     void someFunc() {
>         assert INSTANCE1.getSharedData()==10;
>         assert INSTANCE2.getSharedData()==20;
>         assert INSTANCE3.getSharedData()==40;
>         Instances[] values = instances.values(); // OK
>         Base2[] values = Base2.values(); // Error: No such method.
>     }
> }
>
> DETAILS
>
> SPECIFICATION:
>
> A concept of an "abstract enum" shall be added to the Java language, denoted by prepending the word "abstract" to an enumerated type declaration, with restrictions as described below.
>
> Rule 1: An enumerated type shall either declare no supertype, or shall declare a supertype which is an abstract enumerated type.
>
> Rule 2: It shall be a compile-time error for an ordinary class to extend an enumerated type, either abstract or not.
>
> Rule 3: Both abstract and non-abstract enumerated types shall implicitly have a supertype (not necessarily a direct supertype) of Enum<E extends Enum<E>>. Thus, within the body of an abstract enumerated type, access to methods of this supertype is allowed.
>
> Rule 4: Abstract enumerated types shall not declare enumerators. The body of an abstract enumerated type shall be syntactically and semantically the same as that of an ordinary abstract class which extends its supertype (see rule 3), except with the restriction that all constructors shall be declared with 'protected' or 'package' access (since the class is abstract and cannot declare instances, constructors can only be invoked by subclasses so there is no need to make them more public than necessary).
>
> Rule 5: In an abstract enum, the compiler shall not generate the methods that it would generate for a non-abstract enumerated type (specifically, the "values()" or "valueOf(String) methods), for an abstract enumerated type. (Since it is illegal for there to be enumerators declared in an abstract enum, these methods would serve no purpose.)
>
> Rule 6: It shall be illegal for the expression used in a 'switch' statement to be an abstract enum type.
>
>
> Specifically, section 8.9 of the JLS3, which currently reads:
>
> "
> An enum declaration has the form:
>
>     EnumDeclaration:
>     	ClassModifiers_opt enum Identifier Interfaces_opt EnumBody
> "
>
> shall be modified to read:
>
> "
> An enum declaration has the form:
>
>     EnumDeclaration:
>     	ClassModifiersopt enum Identifier Super_opt Interfaces_opt EnumBody
> "
>
> Also, section 8.1.1.1 of the JLS3, which currently reads:
>
> "Enum types (§8.9) must not be declared abstract; doing so will result in a compile-time error. It is a compile-time error for an enum type E to have an abstract method m as a member unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method."
>
> shall be modified to read:
>
> "Enum types (§8.9) may be declared abstract. If an enum type is declared abstract, it may declare abstract methods. However, it is a compile-time error for an abstract enum type to declare enum constants. Furthermore, it is a compile-time error for any constructor declared by an abstract enum type to have 'public' or 'private' access.
>
> It is a compile-time error for a non-abstract enum type E to have an abstract method m as a member (either explicitly declared or implicitly inherited from an abstract enum supertype) unless E has one or more enum constants, and all of E's enum constants have class bodies that provide concrete implementations of m. It is a compile-time error for the class body of an enum constant to declare an abstract method.
> "
>
> also, in the same section, the text which currently reads:
>
> "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is private."
>
> shall be modified to read:
>
> "If the enum type has no constructor declarations, a parameterless default constructor is provided (which matches the implicit empty argument list). This default constructor is protected if the enum is abstract, and private if it is non-abstract."
>
> and in the same section, the text which currently reads:
>
> "The direct superclass of an enum type named E is Enum<E>."
>
> shall be modified to read:
>
> "A non-abstract enum type named E has a superclass (either direct or indirect via one or more abstract enums) of Enum<E>."
>
> and in the same section, the text which currently reads:
>
> "
> It is a compile-time error for an enum to declare a finalizer. An instance of an enum may never be finalized.
>
> In addition, if E is the name of an enum type, then that type has the following implicitly declared static methods:
> "
>
> shall be modified to read:
>
> "
> It is a compile-time error for an enum (whether abstract or not) to declare a finalizer. An instance of an enum may never be finalized.
>
> In addition, if E is the name of a non-abstract enum type, then that type has the following implicitly declared static methods:
> "
>
> and in the same section, the text which currently reads:
>
> "
> It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (§15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e.
> "
>
> shall be modified to read:
>
> "
> It is a compile-time error for a non-abstract enum type to reference one of its static fields which is not a compile-time constant (§15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e. Note however that any code within a non-abstract enum type may legally reference static fields of its abstract enum supertypes, if such supertypes and fields exist.
> "
>
>
>
>
> and in section 14.11 ('The switch statement'), the text which reads:
>
> "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (§8.9), or a compile-time error occurs."
>
> shall be modified to read:
>
> "The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or a non-abstract enum type (§8.9), or a compile-time error occurs."
>
>
>
> COMPILATION:
>
> An abstract enumerated type with no declared supertype, such as:
>
> abstract enum Foo {
>    ,,,
> }
>
> shall be desugared to code resembling:
>
> @AbstractEnum
> abstract class Foo<E extends Enum<E>> extends Enum<E> {
>     ...
> }
>
> where "@AbstractEnum" is a private compiler-generated annotation similar to the one which is currently used to mark normal enumerated types, and in the same package. Like the annotation which is currently used to mark enumerated types, the @AbstractEnum annotation shall not be visible to ordinary users in source code form -- it exists solely in class files, to allow the compiler to distinguish an abstract class which was declared with the "abstract enum" syntax from one which was declared with the "abstract class" syntax, for the purpose of determining whether an attempt by one class to inherit from another (which may not be supplied in source code form) is legitimate.
>
> An abstract or non-abstract enumerated type with a declared supertype (which must be an abstract enumerated type), such as:
>
> abstract enum Foo1 extends Bar {
>    ...
> }
>
> enum Foo2 extends Bar {
>    ...
> }
>
>
> shall be desugared to code resembling:
>
> @AbstractEnum
> abstract class Foo1<E extends Enum<E>> extends Bar<E> {
>    ...
> }
>
> @...
> class Foo2 extends Bar<Foo2> {
>    ...
> }
>
>
> When compiling such a class, the compiler shall emit a compile-time error if an enum (abstract or not) extends a supertype S unless the following is true:
>
> 1) Either S is declared as an "abstract enum" (if specified in source code form) or S is declared with the @AbstractEnum annotation (if specified in binary class file form), or the erasure of S is the type java.lang.Enum.
>
> 2) Regardless of whether S and its supertypes are declared in source code form or in binary class file form, all supertypes of S shall obey these same constraints.
>
> Furthermore, if a normal class is declared like so:
>
> class Bar extends Baz {
> }
>
> it shall be a compile-time error if class Baz is declared in source code to be an abstract enum, or if its binary class file representation has the @AbstractEnum annotation.
>
> The Java compiler currently generates certain methods, such as values() and valueOf(String) for enumerated types. It shall not generate these for abstract enumerated types. That is, the following shall be a compile-time error:
>
> abstract enum Foo {
> }
>
> void bar() {
>     Foo[] foo1 = Foo.values(); // Error: no such method as 'Foo.values()'
>     Foo foo2 = Foo.valueOf("whatever"); // Error: no such method as 'Foo.valueOf(String)'
> }
>
>
> SIMPLE EXAMPLE:
>
> These classes might be desugared to:
>
> @AbstractEnum
> abstract class SuperEnum<E extends Enum<E>> extends Enum<E> {
>     int getTheAnswerToTheUltimateQuestion() {
>          return 42;
>     }
> }
>
> @...
> class MyEnum extends SuperEnum<MyEnum> {
> // The majority of this non-abstract enumerated type,
> // including generated methods and annotations, is exactly
> // the same as the Java compiler would generate
> // prior to this proposal. However, note that due to
> // this proposal, it has a supertype of "SuperEnum<MyEnum>"
> // instead of "Enum<MyEnum>".
> }
>
> ADVANCED EXAMPLE:
>
> These classes might be desugared to:
>
> @AbstractEnum
> abstract class Base1<E extends Enum<E>> extends Enum<E> {
>     protected final int sharedData;
>     public int getSharedData() {return sharedData;}
>     protected Base1(int sharedData) {
>         this.sharedData = sharedData;
>     }
> }
>
> @AbstractEnum
> abstract class Base2<E extends Enum<E>> extends Base1<E> {
>     protected final int otherSharedData;
>     public int getOtherSharedData() {return sharedData;}
>     protected Base2(int sharedData, int otherSharedData) {
>         super(sharedData);
>         this.otherSharedData = sharedData;
>     }
> }
>
> @...
> class Instances extends Base2<Instances> {
> // The majority of this non-abstract enumerated type,
> // including generated methods and annotations, is exactly
> // the same as the Java compiler would generate
> // prior to this proposal. However, note that due to
> // this proposal, it has a supertype of "Base2<Instances>"
> // instead of "Enum<Instances>".
> }
>
>
> TESTING:
>
> Testing can be accomplished by declaring various abstract enumerated types, having them extend each other, and having non-abstract enumerated types extend them. Normal inheritance relations (method overriding, etc.) should exist among the resulting types.
>
> Furthermore, at least one test should ensure that an attempt to extend an abstract enum (either specified in source or binary form) with a normal class is considered illegal, as is an attempt to have a non-abstract enum or an abstract enum extend a class which is not an abstract enum.
>
> Furthermore, a test should ensure that an attempt to use an expression whose compile-time type is that of an abstract enum in a 'switch' statement is considered illegal.
>
> Furthermore, a test should ensure that an attempt to reference the "values()" or "valueOf()" methods of an abstract enum is considered illegal.
>
>
> LIBRARY SUPPORT:
>
> No changes to supporting libraries are needed, except for the addition of the "@AbstractEnum" annotation type as mentioned above.
>
> REFLECTIVE APIS:
>
> The "Class.isEnum()" method shall return false when invoked on an abstract enum. (This is necessary to avoid unexpected side effects in methods which currently depend on identifying concrete enumerated types with this method. Technically, despite the syntax used to declare them, abstract enums aren't really enums -- they are just supertypes of them, and so should be treated basically exactly the same as class Enum<T> is for the purposes of reflection, etc. This should be documented clearly in the javadoc for Class.isEnum())
>
> It may be desirable to create a "Class.isAbstractEnum()" convenience method to detect the @AbstractEnum annotation. For consistency, such a method should probably return 'true' when invoked on the Enum<T> supertype as well.
>
>
> OTHER CHANGES:
>
> Javadoc might possibly need to be updated to handle the possibility of generating documentation for an abstract enumerated type.
>
> In order to allow abstract supertypes to be added or removed from an abstract enum without making it impossible to read back existing serialized data, it will be necessary to modify the Java serialization specification as follows:
>
> In section "1.12 Serialization of Enum Constants", the following text shall be added at the end of the section:
>
> "
> Furthermore, in order to preserve the ability to deserialize enumerated constants which may have been serialized with an enumerated type having a different type hierarchy from what was written (due to the addition or deletion of "abstract enum" supertypes), the type of every enumerated constant shall be serialized and deserialized as if the immediate supertype of the declared non-abstract enum type which defines the constant was java.lang.Enum. In particular, a type such as:
>
> abstract enum Foo {
> }
>
> abstract enum Bar extends Foo {
> }
>
> enum Baz extends Bar {
>     QUX;
> }
>
> shall exist in serialized form exactly as if it were declared as:
>
> enum Baz { // implicit supertype of Enum<T extends Enum<T>>
>     QUX;
> }
> "
>
> MIGRATION:
>
> New abstract enumerated types can be created, as desired, to do code sharing between existing non-abstract enumerated types in an existing code base.
>
> The above "OTHER CHANGES" section ensures that adding or removing abstract supertypes of an enum will not affect the ability to serialize or deserialize instances of it.
>
> COMPATIBILITY
>
> BREAKING CHANGES:
>
> Since this syntax was previously considered a syntax error, no previously valid programs will be invalidated by it.
>
> EXISTING PROGRAMS:
>
> This feature should not change the semantics of existing class files. The features being added should desugar to normal method calls, class declarations, etc. Hence, I do not anticipate problems interacting with existing class files.
>
> REFERENCES
>
> EXISTING BUGS:
>
> Add language support for abstract Enum's
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6507006
>
> allow "abstract enum AbstractEnum" and "enum MyEnum extends AbstractEnum"
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222244
>
> Support for public abstract enum declaration
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6570766
>
> (The original enum proposal, the comments for which allude to the possibility of abstract enums)
> Bug ID: 4401321 Add type-safe enums to Java
> http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4401321
>
>
> URL FOR PROTOTYPE (optional):
>
> Although not implemented in response to this specific proposal, Fred Simon has implemented a substantially similar feature in Kijaro:
>
> http://tech.puredanger.com/2008/01/10/property-enum/
>
>
>
>   





More information about the coin-dev mailing list