PROPOSAL: Abstract enums (version 3)

Derek Foster vapor1 at teleport.com
Thu May 7 01:27:15 PDT 2009


Per feedback on the Project Coin mailing list, this proposal has been revised once again to replace discussion of the @AbstractEnum annotation with a class file attribute, ACC_ABSTRACTENUM, and provide more explanation of its intended use and meaning. Additionally, this version addresses another suggested workaround for the problem being addressed (Thanks, Joe!), corrects a flaw in the suggested desugarings of prior versions (thanks, Bruce!) and adds to the ALTERNATIVES section some discussion of a minor possible extension to the proposal: the possibility of access to the type of the concrete subtype of the enum using a generic type parameter (thanks again, Bruce!)

Abstract Enums (Version 3)

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 it via 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 are problems for "extensible enums" approaches and which have therefore 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.

Another possible attempt to deal with this issue (suggested on the Project Coin mailing list by Joe Darcy), would be to rewrite the above example like so:

class TableEnumGuts {
    private final String tableName;
    private final String columnName;
    private final Access access;
    protected TableEnumGuts(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;
    public TableEnumGuts getGuts() {
        return guts;
    }
    private PersonTable(String columnName, Access access) {
        guts = new TableEnumGuts("PersonTable", columnName, access);
    }
    @Override
    final String toString() {
        return guts.toString();
    }
}

enum PetTable extends TableEnum {
    PETNAME_COLUMN("PetName"),
    SPECIES_COLUMN("Species");
    private TableEnumGuts guts;
    public TableEnumGuts getGuts() {
        return guts;
    }
    private PersonTable(String columnName) {
        guts = new TableEnumGuts("PersonTable", columnName, access);
    }
    @Override
    final String toString() {
        return guts.toString();
    }
}

Note that this rewrite has improved one aspect of the problem (it has substantially reduced the amount of duplicate boilerplate code due to forwarding methods) at the cost of introducing another concern: it has changed the interface to the class in order to deal with this implementation problem. In particular, calling a method on an instance of one of the above enums now requires the syntax "foo.getGuts().getColumnName()" instead of the prior "foo.getColumnName()". Note that besides being more verbose and thus contributing to cluttered code in the clients, this refactoring will also unfortunately force the source and binary code in the clients to change. Thus, if the enum in question is part of the public API to a library (a JAR file), for instance, upgrading to a new version of the library which attempts to introduce a "extract supertype" refactoring from two related enums will be a breaking change to any source or class files that depended on the old interface to the library.

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, without introducing the drawbacks that exist due to the second and third approaches.


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 workarounds being used above. These allows subtypes to share code, but results in potentially large numbers of forwarding methods and/or difficulties with code maintenance and refactoring.

As a minor variation to this proposal, Bruce Chapman has suggested (on the Project Coin mailing list) that it might be desirable for an abstract enum to be able to reference the subtype that is being instantiated by using a generic type parameter, as Enum<T> can. It might be possible, for instance, to slightly abuse the generic typing mechanism to declare a type such as:

abstract enum Foo<E> extends Bar {
    E getSuccessor() { return getDeclaringClass().getEnumConstants()[ordinal()+1];}
}

where the generic type parameter E would be considered to have the type "E extends Foo<E>".

This proposal does not currently attempt to provide such a feature, primarily since it is not expected to be frequently needed and because in those few cases where it is needed, existing mechanisms (method overloading with covariant return types, for instance) can provide the necessary interface in many cases without a great deal of extra code (usually, a single one-line forwarding/casting method per non-abstract enum class that delegates to a superclass method). However, such a feature could be considered a natural extension of this proposal and could be implemented if it turns out to be needed often enough to outweigh the somewhat nonintuitive syntax.

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."


and in the JVM specification (version 2) in the section "Class file format", in table 4.1 ("Class access and property modifiers") the following entry shall be added after the ACC_ENUM entry:

ACC_ABSTRACTENUM 0x8000 Declared as an abstract enum type

and in the same section, the text 

"The ACC_ENUM bit indicates that this class or its superclass is declared as an enumerated type"

shall be replaced with:

"
The ACC_ENUM bit indicates that this class or its superclass is declared as a non-abstract enumerated type. (Note that a class having this attribute may be DECLARED as non-abstract in source code, but may still actually be abstract (and hence have the ACC_ABSTRACT bit) due to having abstract methods and anonymous subtypes which provide implementations of them). If this bit is set, the ACC_ABSTRACTENUM bit must not be set.

The ACC_ABSTRACTENUM bit indicates that this class is declared as an abstract enumerated type. If this bit is set, the ACC_ENUM bit must not be set.
"

In the Java serialization specification, 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;
}
"


COMPILATION:

An abstract enumerated type with no declared supertype, such as:

abstract enum Foo {
   ,,,
}

shall be desugared to code resembling:

// with the ACC_ABSTRACTENUM bit set in the access_flags field of the corresponding class file...
abstract class Foo<E extends Foo<E>> extends Enum<E> {
    ...
}

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:

// with the ACC_ABSTRACTENUM bit set in the access_flags field of the corresponding class file.
abstract class Foo1<E extends Foo1<E>> extends Bar<E> {
   ...
}

// with the ACC_ENUM bit set in the access_flags field of the corresponding class file (as it would be prior to this proposal)...
class Foo2 extends Bar<Foo2> {
   ...
}


When compiling such a class, the compiler shall emit a compile-time error if a declared 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 ACC_ABSTRACTENUM bit set (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 ACC_ABSTRACTENUM bit set.

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:

// Note: ACC_ABSTRACTENUM set in class file
abstract class SuperEnum<E extends SuperEnum<E>> extends Enum<E> {
    int getTheAnswerToTheUltimateQuestion() {
         return 42;
    }
}

// Note: ACC_ENUM set in class file as it was prior to this proposal
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:

// Note: ACC_ABSTRACTENUM set in class file
abstract class Base1<E extends Base1<E>> extends Enum<E> {
    protected final int sharedData;
    public int getSharedData() {return sharedData;}
    protected Base1(int sharedData) {
        this.sharedData = sharedData;
    }
}

// Note: ACC_ABSTRACTENUM set in class file
abstract class Base2<E extends Base2<E>> extends Base1<E> {
    protected final int otherSharedData;
    public int getOtherSharedData() {return sharedData;}
    protected Base2(int sharedData, int otherSharedData) {
        super(sharedData);
        this.otherSharedData = sharedData;
    }
}

// Note: ACC_ENUM set in class file as it was prior to this proposal
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.

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 ACC_ABSTRACTENUM class file 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.

Changes to the class file format (addition of the ACC_ABSTRACTENUM bit) are noted in the specification section above.

Changes to the Java serialization format (serialization of enums with abstract supertypes as if they did not have such supertypes) are noted in the specification section above.

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.

This format will require an increase in the class file version number, which is expected for Java 7 anyway.

EXISTING PROGRAMS:

This feature should not change the semantics of existing class files (other than to require that they be regenerated with an appropriate version number corresponding to the JDK 7 class file format). The features being added should desugar to normal method calls, class declarations, etc.

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