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, enum
s can implement interface
s.
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 enum
s 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
How to Distinguish Between Multiple Uipickerviews on One Page
Uitextview Font to Always Be Fixed Size
Swift 5 Table View Cell with Uiimage Appears Very Tall and Image Extremely Zoomed
How to Make Swiftui Listmenu with Different Behaviors
Init an Object Conforming to Codable with a Dictionary/Array
Delegate Methods in Child Class Sometimes Not Called with Swift 5 Compiler
Swiftui Change View with Button
When Calling a Function in Swift, What Does Each Part Mean
Xcode & Swift - Window Without Title Bar But with Close, Minimize and Resize Buttons
Build Input File Cannot Be Found' Swift 4.2, Xcode 10.0
Pagination with Firebase Firestore - Swift 4
How to Display Image from a Url in Swiftui
Environmentobject VS Singleton in Swiftui
Xcode 6.3 Code Completion Too Slow
Difference Between Type Method and Type Instance Method, etc
Uiview Background Color in Swift
How to Get Iobluetoothdevice's Battery Level, Using Swift and Appkit (Xcode for MACos)