Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 6570766
Votes 19
Synopsis Support for public abstract enum declaration
Category java:specification
Reported Against
Release Fixed
State 6-Fix Understood, request for enhancement
Priority: 5-Very Low
Related Bugs 6507006 , 6191812 , 6222244
Submit Date 18-JUN-2007
Description
A DESCRIPTION OF THE REQUEST :
Give the ability to create abstract classes between the final enum declaration containing the static enumerated values, and the abstract superclass for all enum java.lang.Enum.
So an AbstractColumn.java file can contain:
public abstract enum AbstractColumn {
   String columnName;
   int precision;
    AbstractColumn() {
       columnName = name();
       precision = 0;
   }
  AbstractColumn(String c, int p) {
   ....
   }
   public String getColumnName() {return columnName();}
}

And inside an O/R Mapping framework an annotation can be:
public interface @Column {AbstractColumn definition();}

And then the application users have the level of indirection they need to provide logic to the framework using the static annotations. For example:
public enum CustomerColumn extends AbstractColumn {
  firstName, lastName, age;
   public String getColumnName() {
      return StringUtils.capitalizeWithUnderscore(name());
   }
}

@Entity
public class Customer {
  @Column(definition = CustomerColumn.firstName)
  private String firstName;
}

Then all the problems of hardcoded schema names, copy/paste, string based errors (no type safety), and so on disappear.
  From my experience, the limitations of Annotations are really pushing developers away, and this feature can unlock the issue.

JUSTIFICATION :
The request was already reported in Bug ID: 6222244 and Bug ID: 6507006.
For example: http://beust.com/weblog/archives/2004_04.html
There is a big demand to have more flexible annotations, and one big solution is this one: Have the user define its own enum classes that extends a specific abstract enum provided by the framework, and use this specific enum in the framework annotations.
With this, if you want to redirect to XML configuration, nothing stops you...


---------- BEGIN SOURCE ----------
/*
 * @test @(#)AE1.java	1.7 08/06/07
 * @summary support for abstract enum
 * @author freds
 *
 * @compile AE1.java
 */

package abstractEnum.ae1;

public abstract enum AE1 {
    int i;
    AE1() {i=2;}
    AE1(int pi) {i=pi;}
    public int getI() {return i;}
}

/*
 * @test @(#)E1.java	1.7 08/06/07
 * @summary support for abstract enum
 * @author freds
 *
 * @compile AE1.java E1.java
 */
public enum E1 extends AE1 {
    one(1),two;
    E1() {
    }
    E1(int pi) {
        super(pi);
    }
}

/*
 * @test @(#)AnnoAETest.java	1.7 08/06/07
 * @summary support for abstract enum
 * @author freds
 *
 * @compile AnnoAETest.java
 */
public @interface AnnoAETest {
    AE1 ae1();
}

/*
 * @test @(#)AnnoAEUsage.java	1.7 08/06/07
 * @summary support for abstract enum
 * @author freds
 *
 * @compile AnnoAEUsage.java
 */
public class AnnoAEUsage {
    @AnnoAETest(ae1 = E1.one)
    private String fisrt;
}

---------- END SOURCE ----------
Posted Date : 2007-06-18 16:39:15.0
Work Around
N/A
Evaluation
From the JSR201 FAQ:

"With the Typesafe Enum pattern described in Effective Java, it is
possible to subclass an enumerated type. Why is this not allowed by the
language feature?

The semantics of inheritance for enum types is too confusing. People
expect subclasses to contain the enumeration constants from both the
superclass and the subclass, but they contain only the subclass
constants. Further, the compiler generates two static methods for each
enum class providing operations on the entire class (values() and
valueOf(String)). These methods are defined using the list of constants
found in the enum declaration, hence subclassing would break them. More
seriously, allowing subclassing of enums would render switch statements
ambiguous if multiple subclasses of an enum class contained enum
constants with the same simple name. All things considered, the
complexity inherent in allowing subclassing is too great to justify it."

The text above discusses arbitrary subclassing. I see from your site [1] that you do not permit arbitrary subclassing - all you allow is an abstract enum (without constants) subclassed directly by one or more non-abstract enums. That supports your particular use case:
1) An abstract enum contains code only.
2) Constants are only defined in a non-abstract enum 'subclass', and are always referenced as members of that subclass. (More generally, constants are always used in a context where they are members of a particular subclass.)

(2) avoids the first problem from the FAQ. (2) also explains why you are are prepared to restrict switches to variables of NON-abstract enum type, and it makes the third problem goes away.

The second problem is tricky. Your abstract enums are enums so they must support values(). What do you return? You could return an empty collection, but that is not in keeping with the aim of enums as outlined by Neal Gafter [2]:
 
"First, the whole idea of an enum is that you statically enumerate ALL the members of the type. If you can extend the type and add members (via subclasses) later, then the purpose is defeated. Members of the extended enum are indeed values of the base enum type, as it is a subtype. So the must be listed in the VALUES of the base class. Ignoring the question of how the compiler can possibly arrange that, is this really what anyone would want?"

Overall, there may be some merit in your use case. We will not rush into extending the design space of enums, particularly in ways contrary to JSR201's intent, but I will keep this request around to track the KSL work.

[1] http://www.jfrog.org/wiki/index.php/Fred:Abstract_Enum_Patch
[2] http://forum.java.sun.com/thread.jspa?threadID=427486&messageID=1932298
Posted Date : 2007-06-19 14:04:35.0
Comments
  
  Include a link with my name & email   

Submitted On 22-JUN-2007
freddy33
I agree with enum inheritance being confusing, but here it's the declaration of "abstract enum" which is not an enum. By definition an abstract class cannot be instantiated, so an abstract enum cannot have constant instances.
In the KSL patch I provide the method AbstractEnum.values() and AbstractEnum.valueOf() are not created and so don't exists for abstract enum. It sounds logical to me that you cannot get an instance of an abstract enum (class)!
For the switch statement, one of the test I wrote is to make sure it fails when applied on an "abstract enum".
So, basically, "abstract enum" is more like allowing to extend java.lang.Enum so it can be used for real enum. "Abstract Enum" are not enum.


Submitted On 29-JUN-2007
scockroach
Would this enhancement also make it possible to create an annotation like:

public @interface MyAnnotation {
  Enum someEnum;
}

Even if it didn't.  This enhancement would solve my biggest complaint with annotations and would give us a lot of the flexibility we've been looking for.


Submitted On 29-JUN-2007
hlovatt
It would be nice if enum could extend any non-final class, like it can implement an interface. But note I am not proposing that it could extend another enum class, since an enum is final and to me the semantics aren't clear.

If the super class had constructors that require arguments then you could wite a constructor in the enum that could be used by the enum values. If the super class had a default constructor then you wouldn't have to write a constructor in the enum. If the super class only had constructors with arguments then you must write at least one enum constructor. IE like normal Java.

This would be more flexible for me; I often have to use an interface and a utility class with implementations in it so that I can implement the interface in the enum and then forward the methods to the utility class to 'inherit' implementation of common methods.

I don't see there is a problem conceptually, though there may well be due to implementation details, with extending a class hierarchy; since you still have a fixed set of enum values and you can only switch on an enum.


Submitted On 01-JUL-2007
freddy33
The main reason for the superclass of an enum to be another "abstract enum" is to be able to use the AbstractEnum class in Annotations, and to avoid complications in the automatic generation (synthetic sugar in javac) of all the enum features (and there is quite a bunch).
So:
public @interface MyAnnotation {
  Enum someEnum;
}
Is not accepted since Enum is a class. But
public @interface MyAnnotation {
  FrameworkAbstractEnum someEnum;
}
is allowed and MyAnnotation and FrameworkAbstractEnum does not know a-priori the different enum types that will implement the "abstract enum". But when using the annotation, the actual enum entry need to be provided.
The patch allow that already, and is solving mine also:
"biggest complaint with annotations and would give us a lot of the flexibility we've been looking for."


Submitted On 02-JUL-2007
scockroach
I don't understand the difference.  java.lang.Enum is a public abstract class.  FrameworkAbstractEnum is also a public abstract class.  Or is that FrameworkAbstractEnum is declared as an enum so it's handled differently by the Java run-time?


Submitted On 03-JUL-2007
freddy33
Yes "public abstract class Enum" and "public abstract enum FrameworkAbstractEnum" makes the difference. FrameworkAbstractEnum is flagged as being an enum that cannot be instantiated, does not have values() and valueOf() and cannot be used in switch{} but still an enum for annotation.


Submitted On 01-AUG-2007
I strongly support this RFE, I often have a need for this, not necessarily related with annotations. t's pretty simple; just let

    abstract enum EnumA extends Enum { ... }

expand to a class

    abstract class EnumA<E extends EnumA<E>> extends Enum<E> { ... }

and

    abstract enum EnumB extends EnumA { ... }

to a class

    abstract class EnumB<E extends EnumB<E>> extends EnumA<E> { ... }

and finally

    enum EnumC extends EnumB { ... }

to a conrete enum class

    class EnumC extends EnumB<EnumC> { ... }

and you're set. Of course Enum.valueOf() and Class.getEnumConstants() would only be applicable to concrete enum types.


Submitted On 12-AUG-2007
I recently had a case where I needed to have a whole group of enum types that all needed to implement a common interface. It was a royal pain in the *$$ to have to implement each method of that interface again in each type (I ended up having to make forwarding calls to an external set of static methods that did the actual implementation. Ugly). I definitely support this proposal. 

Also, I agree with freddy33, above, in that I don't think that an abstract enum needs to support the 'values()' and 'valueOf()'  methods. These are compiler-generated static methods anyway, on the subtype (there is no declaration of them in class Enum), so it is not a even violation of the Liskov Substitution Principle for an abstract enum not to support them. Yes, it might require a minor change to the Java Language Standard to note that these methods aren't provided for enums which are declared 'abstract', but I don't see that as a big deal.


Submitted On 20-JAN-2009
satishv
I like the concept of abstract enums.


Submitted On 18-JUN-2009
Dariusz_Wawer
Many times I have found myself in need of a mechanism which would allow me to ensure correct values passed to subslasses of an abstract class. 

For example, an abstract class allows for defining fields of a packet and assigning each a value. Fields themselves are defined in a subclass. As of now, the String enum pattern can be used to define fields names, though each time a value is assigned the class must check for String's validity and throw an exception in case of an error.

Using abstract enum and defining enum values in the subclass would, first of all, ensure correctness of each field's name, since when passing a parameter an element of Enum would be passed, and not a String. Therefore the need for checking the name would disappear.

I strongly support the concept of abstract enums.



PLEASE NOTE: JDK6 is formerly known as Project Mustang