Can You Extend an Enum

Can enums be subclassed to add new elements?

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.

Is it possible to extend Java Enums?

No it's not possible. The best you can do is make two enums implement and interface and then use that interface instead of the enum. So:

interface Digit {
int getValue();
}

enum Decimal implements Digit {
ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE;

private final int value;

Decimal() {
value = ordinal();
}

@Override
public int getValue() {
return value;
}
}

enum Hex implements Digit {
A, B, C, D, E, F;

private final int value;

Hex() {
value = 10 + ordinal();
}

@Override
public int getValue() {
return value;
}
}

Extending an enum via inheritance

The reason you can't extend Enums is because it would lead to problems with polymorphism.

Say you have an enum MyEnum with values A, B, and C , and extend it with value D as MyExtEnum.

Suppose a method expects a myEnum value somewhere, for instance as a parameter. It should be legal to supply a MyExtEnum value, because it's a subtype, but now what are you going to do when it turns out the value is D?

To eliminate this problem, extending enums is illegal

Why can't a class extend an enum?

I think an answer to why they did it this way comes from this question:

In your example, how would you instantiate a MyClass? Enums are never explicitly instantiated (via a new MyEnum()) by the user. You'd have to do something like MyClass.ASD but not sure how that would work.

Basically, I don't know what syntax would work for your proposed addition. Which is probably why they made them final etc...

EDIT ADDED

If the author of the original Enum planned ahead (unlikely), and you are not worried too much abut thread safety, you could do something like this: (BTW, I'd probably scream at anybody who actually did this in production code, YMMV)

public enum ExtendibleEnum {

FOO, BAR, ZXC;

private Runnable anotherMethodRunme; // exact Interface will vary, I picked an easy one
// this is what gets "injected" by your other class

public void setAnotherMethodRunMe(Runnable r) { // inject here
anotherMethodRunme= r;
}

public void anotherMethod() { // and this behavior gets changed
anotherMethodRunme.run();
}
}

Extending Enum in typescript



Currently, You can't extend enum in TypeScript

Another option is to use type:

enum Color1 {
Red = "Red",
Green = "Green"
}

enum Color2 {
Yellow = "Yellow",
Blue = "Blue"
}

define a new type named Colors :

type Colors = Color1 | Color2;

Then you can use it as below :

class AppComponent {
public color: Colors;

ngOnInit(): void {
const Colors = { ...Color2, ...Color1 };
this.color = Colors.Red; // Colors.Green or Colors.Yellow or Colors.Blue
}
}

Stackblitz Here (Angular)

Stackblitz Here (Typescript)

How to extend Python Enum?


Subclassing an enumeration is allowed only if the enumeration does not define any members.

Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances.

https://docs.python.org/3/library/enum.html#restricted-enum-subclassing

So no, it's not directly possible.

How to enable enum inheritance

You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.

However, enums can implement interfaces.

What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.

Then your enum values would be referred to by their common interface.

In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.

That would force implementing enums to provide an implementation for that method.

This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.

Self-contained example (don't mind the lazy names here)

package test;

import java.util.ArrayList;
import java.util.List;

public class Main {

public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}

static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}

Output

first
POST

Extending a enum in Java

You can't.

Enum types are final by design.

The reason is that each enum type should have only the elements declared in the enum (as we can use them in a switch statement, for example), and this is not possible if you allow extending the type.

You might do something like this:

public interface MyInterface {
// add all methods needed here
}

public enum A implements MyInterface {
A, B;
// implement the methods of MyInterface
}

public enum B implements MyInterface {
C;
// implement the methods of MyInterface
}

Note that it is not possible to do a switch with this interface, then. (Or in general have a switch with an object which could come from more than one enum).

Why can't an enum extend a class in Java?

An enum cannot extends another class because an enum already extends Enum<T>. That class provides all the enum functionality.

An enum can, however, implements an interface:

public interface DegreesMeasure {
double getDegrees();
}

public enum E3 implements DegreesMeasure {
NORTH(0),
EAST(90),
SOUTH(180),
WEST(270);

private final double degrees;

E3(double degrees) {
this.degress = degrees;
}

@Override
public double getDegrees() {
return degrees;
}
}

And this would seem to make a lot more sense in your case anyway.

Also, traditionally, as an enum value is in essence a public static final value it is named in the same way - in block caps with underscores.

EDIT

From comments - how to override methods in individual enum values. This is often used in a Factory Pattern. Assume we have a Widget and a WidgetFactory. We have two different widget types, small and large. These are represented by the classes SmallWidget and LargeWidget.

interface Widget {}

interface WidgetFactory {
Widget get();
}

class LargeWidget implements Widget {}

class SmallWidget implements Widget {}

Now we can implement the WidgetFactory as an enum thus:

enum WidgetFactoryImpl implements WidgetFactory {
SMALL {
@Override
public Widget get() {
return new SmallWidget();
}
},
LARGE {
@Override
public Widget get() {
return new LargeWidget();
}
};

}

In general having polymorphic behaviour on enum can be extremely powerful.



Related Topics



Leave a reply



Submit