Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow

Java Abstract Class Implementing an Interface with


Generics
Asked 13 years, 2 months ago Modified 8 years, 3 months ago Viewed 34k times

I am trying to define an abstract class implementing Comparable. When I define the class
with following definition:
73
public abstract class MyClass implements Comparable <MyClass>

subclasses have to implement compareTo(MyClass object) . Instead, I want every subclass to


implement compareTo(SubClass object) , accepting an object of its own type. When I try to
define the abstract class with something like:

public abstract class MyClass implements Comparable <? extends MyClass>

It complains that "A supertype may not specify any wildcard."

Is there a solution?

java generics abstract-class

Share Edit Follow asked Aug 28, 2010 at 23:41


Cem
733 1 5 4

7 Answers Sorted by: Highest score (default)

It's a little too verbose in my opinion, but works:

53 public abstract class MyClass<T extends MyClass<T>> implements Comparable<T> {

public class SubClass extends MyClass<SubClass> {

@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}

Share Edit Follow edited Dec 5, 2010 at 8:44 answered Aug 29, 2010 at 0:03
https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 1/6
11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow

whiskeysierra
5,040 1 29 40

3 Consider (1) class MyImpl1 extends MyClass<MyImpl1> { ... }; and (2) class MyImpl2 extends
MyClass<MyImpl1> { public int compareTo (MyImpl1 o ) {...} }. MyImpl2 is not doing the right thing.
– emory Aug 29, 2010 at 0:41

2 If we assume that every subclass extends MyClass with its own class as the generic parameter, the
solution is correct. However, it seems that there is no way ensure this, as emory pointed out. – Cem
Aug 29, 2010 at 8:46

@emory This is also true for implementing Comparable directly. No one stops you from doing
MyImpl2 implements Comparable<MyImpl1> . – whiskeysierra Aug 29, 2010 at 12:49

1 But declaring the requirement forces sub classes to implement comparable instead of assuming it.
– whiskeysierra Aug 29, 2010 at 16:45

3 public abstract class MyClass<T> implements Comparable<T> is just as good – newacct


Nov 30, 2012 at 10:39

Apart from the mechanical difficulties you're encountering declaring the signatures, the goal
doesn't make much sense. You're trying to establish a covariant comparison function, which
21 breaks the whole idea of establishing an interface that derived classes can tailor.

If you define some subclass SubClass such that its instances can only be compared to other
SubClass instances, then how does SubClass satisfy the contract defined by MyClass ?
Recall that MyClass is saying that it and any types derived from it can be compared against
other MyClass instances. You're trying to make that not true for SubClass , which means that
SubClass does not satisfy MyClass 's contract: You cannot substitute SubClass for MyClass ,
because SubClass 's requirements are stricter.

This problem centers on covariance and contravariance, and how they allow function
signatures to change through type derivation. You can relax a requirement on an argument's
type—accepting a wider type than the supertype's signature demands—and you can
strengthen a requirement on a return type—promising to return a narrower type than the
supertype's signature. Each of these freedoms still allows perfect substitution of the derived
type for the supertype; a caller can't tell the difference when using the derived type through
the supertype's interface, but a caller using the derived type concretely can take advantage of
these freedoms.

Willi's answer teaches something about generic declarations, but I urge you to reconsider
your goal before accepting the technique at the expense of semantics.

Share Edit Follow edited May 23, 2017 at 11:46 answered Aug 29, 2010 at 0:34
Community Bot seh
1 1 15k 2 49 58

I agree with this answer. In addition, we should be coding to interfaces not classes. The actual
implementation class may be an anonymous class, local class (nested inside a method), private

https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 2/6
11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow

(nested inside a class), or package private and thus not within our scope. – emory Aug 29, 2010 at
0:46

2 Another problem I see is storing the subclass objects in a Collection. I should be able to store them
with just List<MyClass> , instead of List<MyClass<?>> . And what would get called when you get
one of those objects and call equals(anObject) ? – TheLQ Aug 29, 2010 at 0:59

seh, thanks for your answer. Actually, I am looking for a contract that will force every subclass to have
a compareTo() method only for its own class, but not for any other subclass. My made-up generics
definition might be misleading in this sense. – Cem Aug 29, 2010 at 8:31

I understand, Cem, though it's still weird to force subclasses to have compareTo() defined. With
Enum , it's providing that definition to derived types -- types that the compiler will generate for you --
and that's an unusual situation. In your case, you're not providing anything but an obligation for derived
types. Is the intention to guarantee that you can write generic functions against type MyType<T> and
be sure that it provides compareTo(MyType<T>) ? If so, couldn't you also do that by having your
function demand <T extends MyType && Comparable<T>> ?. – seh Aug 29, 2010 at 15:04

see Java's own example:

3 public abstract class Enum<E extends Enum<E>> implements Comparable<E>


public final int compareTo(E o)

on seh's comment: usually the argument is correct. but generics makes type relations more
complicated. a SubClass may not be a subtype of MyClass in Willi's solution....

SubClassA is a subtype of MyClass<SubClassA> , but not a subtype of MyClass<SubClassB>

type MyClass<X> defines a contract for compareTo(X) which all of its subtypes must honor.
there is no problem there.

Share Edit Follow edited Nov 30, 2012 at 9:24 answered Aug 29, 2010 at 2:16
Stephan irreputable
41.9k 65 238 331 44.8k 9 65 93

1 That's a good example, though it differs from Cem's original question. Now, I may have been reading
his code too literally; perhaps this is exactly what he was trying to write. In this case, the Comparable
facet of the Enum interface is about what a specific subclass can do with itself (or, rather, instances of
itself), not what it can do with Enum -derived types in general. If that's what Cem was after, then I take
your answer to be more appropriate than mine. – seh Aug 29, 2010 at 2:56

I guess it is OK as long as all subclasses are a subtype of MyClass<?>. I am not sure, though, if it
causes a problem in future steps. This is the first time I am designing with generics. – Cem Aug 29,
2010 at 8:34

This is a bad example. Enum is a special case -- enum types are provided by the language, and have
a specific form (an enum A will implement Enum<A> ) which is not true of user-defined classes in
general. – newacct Nov 30, 2012 at 10:42

I'm not sure that you need the capture:

https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 3/6
11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow

1 First, add the compareTo to the abstract class...

public abstract class MyClass implements Comparable <MyClass> {

@Override
public int compareTo(MyClass c) {
...
}
}

Then add the implementations...

public class MyClass1 extends MyClass {


...
}

public class MyClass2 extends MyClass {


...
}

Calling compare will call the super type method...

MyClass1 c1 = new MyClass1();


MyClass2 c2 = new MyClass2();

c1.compareTo(c2);

Share Edit Follow answered Aug 29, 2010 at 0:05


zevra0
271 1 5

Isn't this exactly the way Cem described his problem? How would you implement compareTo in
MyClass1 or MyClass2 with a different parameter type? – whiskeysierra Aug 29, 2010 at 0:13

Found another solution:

1. Define an interface on the fields which make up the comaprable (e.g ComparableFoo)
1
2. Implement the interface on the parent class

3. Implement Comparable on the parent class.

4. Write your implementation.

Solution should look like this:

public abstract class MyClass implements


ComparableFoo,Comparable<ComparableFoo> {
public int compareTo(ComparableFoo o) {
// your implementation
}
}

https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 4/6
11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow

This solution implies that more things might implement ComparableFoo - this is likely not the
case but then you're coding to an interface and the generics expression is simple.

Share Edit Follow answered Jul 28, 2015 at 2:01


David Levy
587 1 6 9

I like this solution due to it's simplicity – Pehmolelu Aug 24, 2015 at 6:14

public abstract class MyClass<T> implements Comparable<T> {

}
1
public class SubClass extends MyClass<SubClass> {

@Override
public int compareTo(SubClass o) {
// TODO Auto-generated method stub
return 0;
}

Share Edit Follow answered Nov 30, 2012 at 10:43


newacct
120k 29 164 224

This does not limit type parameter T to subclasses of MyClass. – Stevo Slavić Jul 21, 2014 at 9:39

@StevoSlavić: So? It is perfectly type-safe. – newacct Jul 21, 2014 at 19:03

If I understood the original question/example correctly, one of the ideas was in restricting T to
subclasses of MyClass, while compiler does not allow it. – Stevo Slavić Jul 21, 2014 at 21:25

@StevoSlavić: the question wants each subclass to be comparable to that subclass only – newacct Jul
21, 2014 at 21:35

There's nothing preventing you from writing public class SubClass extends MyClass<WhateverClass>
.... – Stevo Slavić Jul 21, 2014 at 22:52

I know you said you want "compareTo(SubClass object), accepting an object of its own type",
but I still suggest declaring the abstract class like this:
0
public abstract class MyClass implements Comparable <Object>

and do an instanceof check when overriding compareTo in MySubClass:

@Override
public int compareTo(Object o) {
if (o instanceof MySubClass)) {

https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 5/6
11/1/23, 3:46 PM Java Abstract Class Implementing an Interface with Generics - Stack Overflow
...
}
else throw new IllegalArgumentException(...)
}

similarly to 'equals' or 'clone'

Share Edit Follow answered Oct 3, 2014 at 1:59


Caroline Even
101 1 3

https://stackoverflow.com/questions/3592939/java-abstract-class-implementing-an-interface-with-generics?newreg=3ba979c7… 6/6

You might also like