3

I have a class

public abstract class AbstractE<T, E extends Enum<E> & Flags>
{
     public interface Flags{} /*marker interface*/
     //... 
     //other code
}

and an interface

public interface IXYZAdapter
{
   public <E extends Enum<E> & Flags> Set<E> getFlags();
}

Where Flags is an interface defined in AbstractE itself.

M extends AbstractE thus:

public class M extends AbstractE<Long, M.EF> implements IXYZAdapter
{
    public enum EF implements AbstractE.Flags{flag1, flag2}
    @Override /*from IXYZAdapter*/
    public Set<M.EF> getFlags()
    {return EnumSet.allOf(EF.class);}
    
}

Now, from the main code, I try to get a handle on the interface IXYZAdapter and invoke the getFlags method

IXYZAdapter adapter = (IXYZAdapter)m; //where m is an instance of AbstractE
Set s = adapter.getFlags();

I get the following compile time error in the main program last line (Set s = adapter.getFlags();)

invalid inferred types for E; inferred type does not conform to declared bound(s)

inferred: AbstractE.Flags

bound(s): java.lang.Enum<AbstractE.Flags>,AbstractE.Flags

What am I doing wrong? I am using Java 6

Edited to specify the error location

5
  • 1
    what line triggers the compiler error? Commented Apr 5, 2011 at 6:43
  • When I try to compile, the line Set s = adapter.getFlags() - generates the error Commented Apr 5, 2011 at 6:50
  • what is return new EnumSet.allOf(EF.class); supposed to mean/do? Commented Apr 5, 2011 at 7:00
  • I removed the "new" keyword before EnumSet.allOf It was typed in there by mistake Commented Apr 5, 2011 at 7:11
  • also your first line public abstract class AbstractE<T, E extends Enum<E> & Flags> gives me compiler error, it needs to be public abstract class AbstractE<T, E extends Enum<E> & AbstractE.Flags>. please use copy/paste when asking this type of intricate question :) Commented Apr 5, 2011 at 7:12

2 Answers 2

2

Try this:

public interface IXYZAdapter <E extends Enum<E> & AbstractE.Flags>
{
   public Set<E> getFlags();
}

And

public class M extends AbstractE<Long, M.EF> implements IXYZAdapter<M.EF> 
{
}

Or

Set<M.EF> s = adapter.getFlags();

The problem is that with Set s = adapter.getFlags(); The system doesn't know which type to infer for E in IXYZAdapter and thus the E in AbstractE doesn't match.

Edit:

Another option might be:

interface IXYZAdapter <E extends Enum<E> & AbstractE.Flags>
{
  public Set<? extends E> getFlags();
}

class M extends AbstractE<Long, M.EF> implements IXYZAdapter<M.EF>
{
  public enum EF implements AbstractE.Flags{flag1, flag2}
  public Set<? extends M.EF> getFlags()
  {return EnumSet.allOf(EF.class);}

}

And the call: Set<? extends AbstractE.Flags> s = adapter.getFlags();

This would allow you to get a set of flags without casting and force the flags to be declared as enum.

Sign up to request clarification or add additional context in comments.

2 Comments

both of these solutions require that the programmer knows the enum type when calling getFlags, or else there are at least warnings.
well, that's not really true actually. depends on how you write the main method :) i'll give an example!
0

using the first solution thomas provided, the main method can be written like this to become warning free without actually having to know about the enum type:

public static void main(String[] args) {
    M m = new M();
    IXYZAdapter<?> adapter = (IXYZAdapter<?>)m;
    Set<?> flags = adapter.getFlags();
    Iterator<?> it = flags.iterator();

    while(it.hasNext()) {
        System.out.println(it.next());
    }
}

3 Comments

You don't get warnings but you'd still have to cast the elements of the set to AbstractE.Flags. In that case I'd change the signature to Set<? extends AbstractE.Flags> getFlags(); and then call Set<? extends AbstractE.Flags> s = adapter.getFlags();.
could you elaborate? this code worked fine, and i got the names of the enums to print this way. it sounds as though you imply that the above code shouldn't work. am i missing something?
No, the code above works. But try this: AbstractE.Flags f = it.next();. You'd have to do this in your case: AbstractE.Flags f = (AbstractE.Flags)it.next();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.