Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum constants implementing generic interfaces in Java

Suppose you have a generic interface:

public interface MyInterface<T> {
    T doSomething();
}

Is it possible to declare an enum that implements MyInterface<T>, but for which which every enum constant implements it for a different value of T? That is, given this enum:

public enum MyEnum {
    FOO,
    BAR,
    BAZ;
}

can we change it so that FOO implements MyInterface<Integer>, BAR implements MyInterface<String>, and BAZ implements MyInterface<List<MyOtherType>>, and make it so that MyEnum overall implements MyInterface<?>? It seems entirely feasible doing this raw, so it may be the case that it can be done in a typesafe manner.

like image 373
Kelvin Chung Avatar asked Nov 03 '12 07:11

Kelvin Chung


People also ask

Can enums implement interfaces Java?

Yes, Enum implements an interface in Java, it can be useful when we need to implement some business logic that is tightly coupled with a discriminatory property of a given object or class. An Enum is a special datatype which is added in Java 1.5 version.

Can enum be generic Java?

Java enums will be enhanced with generics support and with the ability to add methods to individual items, a new JEP shows. Since both features can be delivered with the same code change, they are bundled together in the same JEP. The change only affects the Java compiler, and therefore no runtime changes are needed.

How do you declare a constant in an enum in Java?

An enum is a special class that represents a group of constants. To create an enum, use the enum keyword (instead of class or interface), and separate the constants with a comma. values() method can be used to return all values present inside enum.

Can we add constants to enum?

Enum contastants are static and final by default and cannot be changed after once it is created. Also Enums can be used in Switch statements like int and char data types. We can define values for enum constants at the time of creation, but then we must add a constructor and a field variable for this enum.


1 Answers

No, as amalloy pointed out, Java doesn't allow enums to be declared with type parameters. It becomes clear why if you think about the way enums are meant to be used, for example in a switch.

Also consider how the language would implement generic enums - it isn't trivial. For a generic enum MyEnum<T>, each enum constant would need to resolve T to some specific type, otherwise they wouldn't be constants at all. Consider this:

enum MyEnum<T> {
    FOO; // T is not resolved
}

What is T for FOO here? The language would need a new syntax just to be able to express it, for example:

enum MyEnum<T> {
    FOO<String>;
}

So now we're getting into added complexity for the language in order to support semantics that don't have an overly compelling use case. It's easy to see why the language designers would have simply nixed type parameters for enums.

The workaround:

You can emulate your desired pattern by simply not using an enum. Organize the implementations of your interface into a utility class:

public class MyImplementations {

    public static final MyInterface<Integer> FOO =
            new MyInterface<Integer>() {
                ...
            };

    public static final MyInterface<String> BAR =
            new MyInterface<String>() {
                ...
            };

    public static final MyInterface<List<MyOtherType>> BAZ =
            new MyInterface<List<MyOtherType>>() {
                ...
            };

    private MyImplementations() { }
}

The only thing inherently missing is a way to iterate over the different implementations, as you could have done with MyEnum.values() - but with a hypothetical MyEnum<T>, the most specific type you could iterate over would be MyEnum<?>.

like image 193
Paul Bellora Avatar answered Sep 20 '22 15:09

Paul Bellora