I need several enumerations that have the same fields, constructors, and methods, but different sets of values. I know that enums cannot be inherited in the forehead, but does anyone know how to emulate something like this:

enum Parent { DUMMY_ITEM("", 0); String otherName; int intValue; Parent(String otherName, int intValue) { this.intValue = intValue; this.otherName = otherName; } void setIntValue(int value) { intValue = value; } int getIntValue() { return intValue; } int calcSomething() { return intValue * otherName.length(); } } enum Child1 extends Parent { ACTUAL_CHILD1_ITEM1("CHILD1_ITEM1", 1), ACTUAL_CHILD1_ITEM2("CHILD1_ITEM2", 1), ACTUAL_CHILD1_ITEM3("CHILD1_ITEM3", 1), } enum Child2 extends Parent { ACTUAL_CHILD2_ITEM1("CHILD2_ITEM1", 1), ACTUAL_CHILD2_ITEM2("CHILD2_ITEM2", 1), ACTUAL_CHILD2_ITEM3("CHILD2_ITEM3", 1), } 

So that you can write int i = ACTUAL_CHILD2_ITEM1.getIntValue() , int j = ACTUAL_CHILD1_ITEM3.calcSomething() , etc. It’s ugly to repeat the same code of methods and all fields in different enumerations many times, but you really want to use different sets of values ​​so that they are not confused, and that the IDE prompts the correct names of constants.

  • Is that use interfaces. Or something else from the one suggested here: stackoverflow.com/questions/35650045/… - selya
  • @selya how can I get out with the interfaces? - I thought about it, but could not think of anything. - m. vokhm
  • I will write in the form of an answer, how can I get out, replacing enum with class - selya
  • The method headers, of course, can be put into the interface, but I don’t see a big sense of it - you can’t have fields in the interface, so they must be described in enumerations, then the implementation of the methods will still have to be repeated 10 times, in each enumeration separately - m. vokhm
  • @ m.vokhm why repeat the methods implementation? - Sergey Gornostaev

3 answers 3

The default methods will save the father of Russian democracy:

 interface ArithmeticEnum { String getOperation(); default int apply(int x, int y) { switch (getOperation()) { case "+": return x + y; case "-": return x - y; case "*": return x * y; case "/": return x / y; default: throw new IllegalStateException("Unknow operation!"); } } } public enum BasicOperations implements ArithmeticEnum { PLUS("+"), MINUS("-"), TIMES("*"), DIVIDE("/"); private final String symbol; public BasicOperations(String symbol) { this.symbol = symbol; } public String getOperation() { return symbol; } } 
  • Well, also, in principle, an option, but in my case it seems to be too cumbersome. But I will think in this direction, thank you. - m. vokhm

You can get out through the classes:

 public abstract class E { // базовый enum public final int intValue; public final String stringValue; protected E(int intValue, String stringValue) { this.intValue = intValue; this.stringValue = stringValue; } public void printValues() { System.out.println(intValue + " " + stringValue); } } public class EChild extends E { // наследуемый enum private EChild(int intValue, String stringValue) { super(intValue, stringValue); } public static EChild ENUM_1 = new EChild(1, "someString"); public static EChild ENUM_2 = new EChild(2, "otherValue"); } public class Main { public static void main(String args[]) { EChild e = EChild.ENUM_1; System.out.println(e == EChild.ENUM_1); // true e.printValues(); // 1 someString } } 

Mark the base as abstract , otherwise the protected modifier on the constructor will allow us to create an instance of a class from any class in the same package . In the child class, we mark the constructor as private in order not to allow instantiation from outside.

  • Yes! Not as elegant as we would like, but yes, this is an option, thank you. - m. vokhm

In the comments in English, StackOverflow prompted (and as he himself didn’t realize ???) the simplest option that comes closest to what I want to get: each element of the enumeration simply contains an object that encapsulates all the data and all the functionality. Here is the code illustrating the principle:

  public class Test_enums { // Класс объектов, содержащих данные и методы: static class EnumData { int intValue; String stringValue; EnumData(int intValue, String stringValue) { this.intValue = intValue; this.stringValue = stringValue; } void setNewString(String s) { this.stringValue = s; } public String toString() { return intValue + ": " + stringValue; } int calcSomething() { return intValue * stringValue.length(); } // Anything else... } enum Enum1 { ENUM1_ITEM1(1, "Раз"), ENUM1_ITEM2(2, "Два"); public EnumData data; Enum1(int intValue, String stringValue) { data = new EnumData(intValue, stringValue); } } enum Enum2 { ANOTHER_ENUM_ITEM1(1, "One"), ANOTHER_ENUM_ITEM2(2, "Two"); EnumData data; Enum2(int intValue, String stringValue) { data = new EnumData(intValue, stringValue); } } public static void main(String[] args) { System.out.println(Enum1.ENUM1_ITEM1.data); System.out.println(Enum1.ENUM1_ITEM2.data); System.out.println(Enum2.ANOTHER_ENUM_ITEM1.data); System.out.println(Enum2.ANOTHER_ENUM_ITEM2.data); } }