How to implement enum with generics?

Viewed 95343

I have a generic interface like this:

interface A<T> {
    T getValue();
}

This interface has limited instances, hence it would be best to implement them as enum values. The problem is those instances have different type of values, so I tried the following approach but it does not compile:

public enum B implements A {
    A1<String> {
        @Override
        public String getValue() {
            return "value";
        }
    },
    A2<Integer> {
        @Override
        public Integer getValue() {
            return 0;
        }
    };
}

Any idea about this?

4 Answers

If JEP 301: Enhanced Enums gets accepted, then you will be able to use syntax like this (taken from proposal):

enum Primitive<X> {
    INT<Integer>(Integer.class, 0) {
        int mod(int x, int y) { return x % y; }
        int add(int x, int y) { return x + y; }
    },
    FLOAT<Float>(Float.class, 0f)  {
        long add(long x, long y) { return x + y; }
    }, ... ;

    final Class<X> boxClass;
    final X defaultValue;

    Primitive(Class<X> boxClass, X defaultValue) {
        this.boxClass = boxClass;
        this.defaultValue = defaultValue;
    }
}

By using this Java annotation processor https://github.com/cmoine/generic-enums, you can write this:

import org.cmoine.genericEnums.GenericEnum;
import org.cmoine.genericEnums.GenericEnumParam;

@GenericEnum
public enum B implements A<@GenericEnumParam Object> {
    A1(String.class, "value"), A2(int.class, 0);

    @GenericEnumParam
    private final Object value;

    B(Class<?> clazz, @GenericEnumParam Object value) {
        this.value = value;
    }

    @GenericEnumParam
    @Override
    public Object getValue() {
        return value;
    }
}

The annotation processor will generate an enum BExt with hopefully all what you need!

if you prefer you can also use this syntax:

import org.cmoine.genericEnums.GenericEnum;
import org.cmoine.genericEnums.GenericEnumParam;

@GenericEnum
public enum B implements A<@GenericEnumParam Object> {
    A1(String.class) {
        @Override
        public @GenericEnumParam Object getValue() {
            return "value";
        }
    }, A2(int.class) {
        @Override
        public @GenericEnumParam Object getValue() {
            return 0;
        }
    };

    B(Class<?> clazz) {
    }

    @Override
    public abstract @GenericEnumParam Object getValue();
}
Related