Home > OS >  Implementing Pseudo Enum Inheritance in Java using a Marker Interface
Implementing Pseudo Enum Inheritance in Java using a Marker Interface

Time:04-27

I'm using a Marker Interface to implement pseudo enum inheritance.

Let's say I define Marker class as follows:

public interface FieldInterface

Now I have have 5 enum classes that implement this interface.

enum Field1 implements FieldInterface
enum Field2 implements FieldInterface
enum Field3 implements FieldInterface
enum Field4 implements FieldInterface
enum Field5 implements FieldInterface

Each of the 5 enum "Field" class above defines a list of enums related to that field type. For example, enum Field1 might define enums: Field1A, Field1B, Field1C. Enum Field2 might define enums: Field2A, Field2B, Field2C

Now I need to convert plain text representation of each enum to the corresponding enum (similar to calling enum.valueOf(String)) without knowing which of the 5 enum classes the String belongs to.

One way to achieve this might be through reflection by first retrieving a list of all classes that implement said interface and iterating through all of the 5 enum classes until a match is found. However, I prefer to avoid reflection if possible (mainly due to performance reasons).

What other options are there to solve this problem?

Thanks

CodePudding user response:

A traditional implementation of a Map<String, Enum<?>> with a small complication of handling several enum classes. The static final map instance is defined in an interface and shared across all enums.

class Main {
  public static void main(final String[] args) {
    // Enum classes must be loaded
    System.out.println(Field1.FIELD1A);
    System.out.println(Field2.FIELD2A);
    // new X(){} is a little trick to instantiate an anonymous subclass of X and gain access to get() method. It can be done in several other ways.
    // You can call get() on any enum constant but that would look unintiitve. We need an instance of X and can implement an empty singleton class that implements X just to have an instance to call get() on
    System.out.println(new X(){}.get("FIELD1B"));
  }
}

 /**
  * All enums implement this marker interface and therefore share access to a static map from the name of the enum to its value.
 */
interface X {
  Map<String, X> map = new HashMap<>();


  /**
   * This shared method uses enum's name method to get enum's string representation.
   */
  default void add() {
    map.put(name(), this);
  }

  default X get(String key) {
    return map.get(key);
  }

  /**
   * This method is always overwritten by each enum because all enums have a name() method. It is declared here so that we can provide add() method without requiring name passed as an argument. having a default implementation allows us to new X(){}.
   */
  default String name() {
    return null;
  }
}

enum Field1 implements X {
  FIELD1A, FIELD1B, FIELD1C;
  // We have to call add() to place each enum value in the shared map
  Field1() { add(); }
}

enum Field2 implements X {
  FIELD2A, FIELD2B, FIELD2C;
  Field2() { add(); }
}
  • Related