2

Look at this answer. Everything is good, except that:

public <E extends Enum<E> & MyInterface> E getParametrizedEnum() {
    String someString = "..."
    return MyEnum.valueOf(someString); //compile error here
}

Intellij idea tells me "Required E, found com.mypackage.MyEnum".

Have to be cast like that:

public <E extends Enum<E> & MyInterface> E getParametrizedEnum() {
    String someString = "..."
    return (E) MyEnum.valueOf(someString); //compile error here
}

Is there a way to return parameterized enum with interface without casting?

Community
  • 1
  • 1
Cherry
  • 31,309
  • 66
  • 224
  • 364
  • 4
    Please show us `MyEnum` – Henry Feb 04 '16 at 07:53
  • 3
    It sounds like `MyEnum` doesn't implement `MyInterface`. But if it did, why not just use `MyEnum` as the return type? Or can you return different types of enums? – shmosel Feb 04 '16 at 07:55
  • note that you're not getting any type guarantees for this method. Its return value can be assigned to literally any reference type without compile error: `java.awt.Point p = getParametrizedEnum();` see http://stackoverflow.com/q/338887/3385618 – Bewusstsein Feb 04 '16 at 11:51

1 Answers1

2

The problem is that the method does not return a MyEnum, it returns some class which extends both Enum and MyInterface. Even if MyEnum satisfies those contraints, there might be other enums which also implement MyInterface, and those are not necessarily assigment compatible with MyEnum.

Consider the following program:

interface MyInterface {} 
enum MyEnum implements MyInterface {
    A, B, C
}
enum YourEnum implements MyInterface {
    D, E, F
}

public class Foo
{
    public <E extends Enum<E> & MyInterface> E getParametrizedEnum() {
        String someString = "A";
        return (E) MyEnum.valueOf(someString); 
    }

    public static void main(String... args) {
        Foo foo = new Foo();
        YourEnum b = foo.getParametrizedEnum(); // Ooops!
    }
}

It compiles perfectly fine but throws a ClassCastException at run-time!

But if you return a MyEnum anyway, why do you need generics? You can do:

public MyEnum getParametrizedEnum() {
    String someString = "..."
    return MyEnum.valueOf(someString); 
}
Hoopje
  • 12,677
  • 8
  • 34
  • 50
  • Why would they need to be assignment compatible? I can return an `ArrayList` from a method returning `Iterable`, even though there are other classes that implement `Iterable`. How is this situation different? What could go wrong if the compiler allowed this `return` statement? – Thomas Feb 04 '16 at 08:12
  • But they are assignment compatible. `Iterable a = new ArrayList<>()` is perfectly legal. – Hoopje Feb 04 '16 at 08:15
  • Ohh, I see now. The example you added is illuminating, thanks. – Thomas Feb 04 '16 at 08:25
  • The main problem is to return 2 enums instead of one. That's why I need interface here to restrict enum numbers. It is possible to return an interface, but enum switching is lost in this case :( – Cherry Feb 04 '16 at 08:28