Enum "Inheritance"

Enum Inheritance

This is not possible. Enums cannot inherit from other enums. In fact all enums must actually inherit from System.Enum. C# allows syntax to change the underlying representation of the enum values which looks like inheritance, but in actuality they still inherit from System.enum.

See section 8.5.2 of the CLI spec for the full details. Relevant information from the spec

  • All enums must derive from System.Enum
  • Because of the above, all enums are value types and hence sealed

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

Swift enum inheritance

In Swift language, we have Structs, Enum and Classes. Struct and Enum are passed by copy but Classes are passed by reference. Only Classes support inheritance, Enum and Struct don't.

So to answer your question, you can't have inheritance with Enum (and Struct types). Have a look here:

stackOverflow difference classes vs structs

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

Solution to mimic enum inheritance in cpp

Speaking very generally, enums are just dressed up ints.

enum Fruit { apple, orange};

If you look at the compiled code, you will discover that an apple will be represented by the value 0, and an orange will be represented by the value 1.

enum Drink { water, milk};

Same thing here will happen here. water will be represented by value 0, and milk will be represented by value 1. You can begin to see the obvious problem here.

One, a slightly primitive, solution is equivalent to letting a bull loose in the china shop:

enum Drink { water=2, milk=3};

Now you could cook something up where you're passing in a int value and figure out what exactly was passed in, by its value.

But this will likely require plenty of ugly casts, everywhere. The resulting code, if posted to Stackoverflow, will likely to attract downvotes.

The downvotes will be because there are cleaner solutions that are available in modern, post C++17 world. For starters, you can switch to enum classes.

enum class Fruit { apple, orange};
enum class Drink { water, milk};

This gains additional type-safety. It's not as easy, any more, to assign a Fruit to a Drink. Your C++ compiler will bark, very loudly, in many situations where it would raise a warning. Your C++ compiler will help you find even more bugs, in your code. It is true that this will require a little bit more typing. You will always have to specify enumerated values everywhere with full qualification, i.e. Fruit::apple and Drink::water, when in your existing code a mere apple and water will suffice. But a few extra typed characters is a small price to pay for more type-safe code, and for being able to simply declare:

typedef std::variant<Fruit, Drink> Eatable;

and simply do what you always wanted:

void LetsEat(Eatable eatable){}

and everything will work exactly how you wanted it. LetsEat will accept either a Fruit or a Drink as its parameter. It will have to do a little bit more work, to figure out what's in the std::variant, but nobody ever claimed that C++ is easy.

std::variant is one of the more complex templates in the C++ library, and it's not possible to explain how to use it, fully, in a short paragraph or two on Stackoverflow. But this is what's possible, and I'll refer you to your C++ textbook for a complete description of how to use this template.

Java enum inheritance

Example stolen from here

Because adding elements to an enum
would effectively create a super
class, not a sub class.

Consider:

 enum First {One, Two}   
enum Second extends First {Three, Four}

First a = Second.Four; // clearly illegal
Second a = First.One; // should work

This is the reverse of the way it
works with regular classes. I guess it
could be implemented that way but it
would be more complicated to implement
than it would seems, and it would
certainly confuse people.


JPA Enum Inheritance

Alrght, not sure how Smartphone is NOT Hardware, but okay. Here is how I would do it (Not sure if I discard something you actually need now). Make BillCategory an enum. Add private fields PurchaseType (this could also be another enum containing values like GroceryPurchase or ElectronicPurchase) and Category (this is String and matches the enum name). That should solve your problem with hibernate.

Code illustrating what I mean:

enum BillCategory {

VEGAN("VEGAN", PurchaseType.GroceryPurchase),
VEGETARIAN("VEGETARIAN",PurchaseType.GroceryPurchase),
SMARTPHONE("SMARTPHONE", PurchaseType.ElectronicPurchase);

private String category;
private PurchaseType type;

BillCategory(String category, PurchaseType type) {
this.category = category;
this.type = type;
}

public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

public PurchaseType getType() {
return type;
}

public void setType(PurchaseType type) {
this.type = type;
}

}

enum PurchaseType {
ElectronicPurchase, GroceryPurchase;
}

You should then also annotate private BillCategory billCategory; in your entity class with something like @Enumerated(EnumType.ORDINAL), or some other EnumType, depending on how you want it to be saved in the database



Related Topics



Leave a reply



Submit