Home > Back-end >  Enum with generic base class passed as contructor parameter
Enum with generic base class passed as contructor parameter

Time:11-13

I'm attempting to create an enum whose constructor accepts an object whose base class is a generic class.

I seem to be unable to fetch the underlying generic type from within the enum however, Object gets returned instead of T.

Is there a way to do this?

abstract public class Field<T> {
    abstract public T get();
}

public class IntegerField extends Field<Integer> {
    public Integer get() {
        return 5;
    }
}

public class StringField extends Field<String> {
    public String get() {
        return "5";
    }
}

public enum Fields {
    INTEGER (new IntegerField()),
    STRING  (new StringField());

    private final Field<?> field; // <<--- I can't have Field<T>, enum's can't be generic. :( 

    <T> Fields(Field<T> field) {
        this.field = field;
    }

    public <T> T get() {
        return field.get(); // <<--- Returns Object, not T
    }
}

CodePudding user response:

The issue is that enums can't be generically typed so even if you cast that get call ((T) field.get()) you won't have type safety because it will agree with any assignment (you could compile this successfully for instance: boolean b = Fields.INTEGER.get()).

Just use constants instead:

public final class Fields {
   public static final Field<Integer> INTEGER = new IntegerField();
   public static final Field<String> STRING = new StringField();
}

CodePudding user response:

Why do you think an enum is preferable to this?

public final class Fields {
    public static final Field<Integer> INTEGER = new IntegerField();
    public static final Field<String> STRING = new StringField();

    //private ctor
}

or if you prefer

public final class Fields {
    public static Field<Integer> integerField() {
        return new IntegerField();
    }
    
    public static Field<String> stringField() {
        return new StringField();
    }

    //private ctor
}

Why would I want to call Fields.INTEGER.get() when I can just use Fields.INTEGER?

  • Related