Can enums be subclassed to add new elements?

前端 未结 15 1833
臣服心动
臣服心动 2020-11-22 12:02

I want to take an existing enum and add more elements to it as follows:

enum A {a,b,c}

enum B extends A {d}

/*B is {a,b,c,d}*/

Is this po

相关标签:
15条回答
  • 2020-11-22 12:38

    No, you can't do this in Java. Aside from anything else, d would then presumably be an instance of A (given the normal idea of "extends"), but users who only knew about A wouldn't know about it - which defeats the point of an enum being a well-known set of values.

    If you could tell us more about how you want to use this, we could potentially suggest alternative solutions.

    0 讨论(0)
  • 2020-11-22 12:38

    I tend to avoid enums, because they are not extensible. To stay with the example of the OP, if A is in a library and B in your own code, you can't extend A if it is an enum. This is how I sometimes replace enums:

    // access like enum: A.a
    public class A {
        public static final A a = new A();
        public static final A b = new A();
        public static final A c = new A();
    /*
     * In case you need to identify your constant
     * in different JVMs, you need an id. This is the case if
     * your object is transfered between
     * different JVM instances (eg. save/load, or network).
     * Also, switch statements don't work with
     * Objects, but work with int.
     */
        public static int maxId=0;
        public int id = maxId++;
        public int getId() { return id; }
    }
    
    public class B extends A {
    /*
     * good: you can do like
     * A x = getYourEnumFromSomeWhere();
     * if(x instanceof B) ...;
     * to identify which enum x
     * is of.
     */
        public static final A d = new A();
    }
    
    public class C extends A {
    /* Good: e.getId() != d.getId()
     * Bad: in different JVMs, C and B
     * might be initialized in different order,
     * resulting in different IDs.
     * Workaround: use a fixed int, or hash code.
     */
        public static final A e = new A();
        public int getId() { return -32489132; };
    }
    

    There are some pits to avoid, see the comments in the code. Depending on your needs, this is a solid, extensible alternative to enums.

    0 讨论(0)
  • 2020-11-22 12:38

    Having had this same problem myself I'd like to post my perspective. I think that there are a couple motivating factors for doing something like this:

    • You want to have some related enum codes, but in different classes. In my case I had a base class with several codes defined in an associated enum. At some later date (today!) I wanted to provide some new functionality to the base class, which also meant new codes for the enum.
    • The derived class would support both the base classes' enum as well as its own. No duplicate enum values! So: how to have an enum for the subclass that includes the enum's of its parent along with its new values.

    Using an interface doesn't really cut it: you can accidentally get duplicate enum values. Not desirable.

    I ended up just combining the enums: this ensures that there cannot be any duplicate values, at the expense of being less tightly tied to its associated class. But, I figured the duplicate issue was my main concern...

    0 讨论(0)
提交回复
热议问题