12

Consider this code:

public interface Foo extends Comparable<Foo> {}

public enum FooImpl implements Foo {}

Due to the restrictions of type erasure, I receive the following error:

java.lang.Comparable cannot be inherited with different arguments: <Foo> and <FooImpl>

I have the following requirements:

  • FooImpl needs to be an enum, because I need to use it as a default value in annotations.
  • The contract of my interface is that it needs to be comparable.

I already tried using generic bounds in the interface, but this is not supported in Java.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
soc
  • 27,983
  • 20
  • 111
  • 215
  • Try `public interface Foo` `public enum FooImpl implements Foo, Comparable {...}` – Eran Zimmerman Gonen Aug 23 '11 at 12:28
  • The problem is that `FooImpl` already implements `Comparable`. – soc Aug 23 '11 at 12:33
  • And you just want to show that it does? Write it in a comment. – Eran Zimmerman Gonen Aug 23 '11 at 12:45
  • I need to be able to treat instances of `Role` as `Comparable`, a comment won't help here. – soc Aug 23 '11 at 12:48
  • Just above `public enum...`, add: `//Note: implements Comparable.` – Eran Zimmerman Gonen Aug 23 '11 at 12:50
  • I guess the compiler will ignore that comment ... – soc Aug 23 '11 at 12:51
  • @soc let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/2768/discussion-between-eran-zimmerman-and-soc) – Eran Zimmerman Gonen Aug 23 '11 at 12:54
  • just for the record `FooImpl` is a [terrible naming practice](http://www.vertigrated.com/blog/2011/02/interface-and-class-naming-anti-patterns-java-naming-convention-tautologies/). –  Aug 23 '11 at 13:20
  • @Jarrod, taking your blog post to its logical conclusion: if I have only one implementation of the Truck interface, undistinguished in any way, I should just have a Truck class (presumably in another package). Redundancy is no sin, when it comes to allowing people to quickly grasp a design. The fact that IDE's provide icons to denote interfaces is not a good reason to NOT distinguish them otherwise. I'm not surprised that you had to close off comments. – Ed Staub Aug 23 '11 at 13:49
  • @Ed I closed off comments for SPAM reasons, and to your point, the fact that in Java you say `public interface XXX` and `public class YYY inherits XXX` is already enough distinguishable of that something is an `Interface`. If you can't quickly grasp that `XXX` is an Interface from the code directly you should probably not own a keyboard. –  Aug 23 '11 at 13:52
  • @Jarrod, you should try posting your opinions on this on programmers.stackexchange.com. You could get some other input that way without worrying about spam. You might want to tone down the "and if you don't agree with me you're an idiot" stuff, though - it doesn't wear well. – Ed Staub Aug 23 '11 at 14:36

3 Answers3

13

Enums implement Comparable, so FooImpl ends up extending Comparable twice with incompatible arguments.

The following will work:

public interface Foo<SelfType extends Foo<SelfType>> extends Comparable<SelfType> { ... }

public enum FooImpl implements Foo<FooImpl> { ... }
jvdneste
  • 1,677
  • 1
  • 12
  • 14
12

Enum already implements comparable so you can't override it.

A general answer regarding why-would-an-enum-implement-an-interface.

Community
  • 1
  • 1
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
  • You're avoiding the question. What if it was another interface. – aioobe Aug 23 '11 at 12:29
  • @aioobe huh ? The question asks how to implement an interface that extends comparable – NimChimpsky Aug 23 '11 at 12:31
  • If I want to refer to my enum object via my interface: (`Interface Foo {...} Enum1 implements Foo {...} Foo x1 = Enum1.FIRST;`) and if I also need to use it in a context that requires a `Comparable`, then I have to declare that `Foo extends Comparable?something??>`. Without the (admittedly clunky) typing in @jvdnese's answer, you cannot have two different Enums implement Foo and let the compiler know Foos are Comparable. (It's only a warning, so you *can* get away with just skipping `implements Comparable`). An example with the warning is `TreeSet x = new TreeSet<>();` – Joshua Goldberg Jul 14 '20 at 22:05
1

Actually the error you will get is :

The interface Comparable cannot be implemented more than once with different arguments : Comparable<FooImpl> and Comparable<Foo>

As enum FooImpl already implementing Comparable<FooImpl> implicitly, you can not override it again as Comparable<Foo>.

ramsharma
  • 11
  • 4