5

I am calling a specific class using only its interface. The problem is, the class itself implements Comparable, but because I am referring to the class via a different interface, the compiler does not know it implements Comparable. I'm sure there is an easy solution to this... but I just can't think of it right now.

5 Answers 5

8

Will everything that implements the interface also implement Comparable<T>? If so, I suggest you just make the interface extend Comparable<T>.

Otherwise, you could just cast to Comparable<T> if you happen to know that in this case it will work. Of course, that loses some compile-time type safety, but that's the nature of the beast.

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

3 Comments

Yes, but it isn't working. I have public interface Individual<T> extends Comparable<Individual<T>>, but when I try sort sort a list List<Individual<?>> it won't work.
@Ben: It would have been nice if you'd said that in the question... ideally with some example code. This should be a fairly easy one to reproduce with a short but complete example.
I have been trying lots of things, so I just hoped that the question would be enough.
1

This seems odd to me... if you have main like the following, you can make it work with the Parent interface and Child classes below... but there is an oddity in that you could try to compare a ChildA to a ChildB which probably doesn't make sense to do.

Maybe if you gave us a hint at what the classes/interface are doing we could give a better answer.

public class Main
{
    public static void main(final String[] argv)
    {
        Parent x;
        Parent y;

        x = new ChildA();
        y = new ChildA();
        x.compareTo(y);
    }
}

abstract interface Parent
    extends Comparable<Parent>
{
}

class ChildA
    implements Parent
{
    public int compareTo(Parent o)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

class ChildB
    implements Parent
{
    public int compareTo(Parent o)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

3 Comments

I'm comparing classes that are the same type, but the program is designed in such a way that that class type is a parameter, so some of the classes refer to the interface.
Just like List<T> listA = ArrayList<T>() and List<T> listB = LinkedList<T>() is useful.
Hm, it works if I do public interface MyInterface extends Comparable<MyIterface<?>>
1

I'd suggest you to use Comapartor instead. You can use sort(list, Comparator). Your comparator implementation will cast class to Comparable and use its compare method. So the compiler will be satisfied and you will reuse the existing implementation of compare method.

Comments

1

You can do some freaky generics. Let's say the main interface is Lickable (which defines a method lick()), and you want a method that will process objects which are Lickable and Comparable. You write:

public <LickableAndComparable extends Lickable & Comparable<LickableAndComparable>> void lickGreater(LickableAndComparable a, LickableAndComparable b) {
    if (a.compareTo(b) > 0) a.lick();
    else b.lick();
}

You can then call that with objects of any type which is both Lickable and Comparable. Note that it only works if both arguments share a type which is both Lickable and Comparable to itself. If you only have one class in mind, then this should be fine. You may run into migraine-inducing compiler errors if your usage of the method gets complicated.

1 Comment

Is there not a standard way to do this?
0

Comparable interfaces are tricky. In general, if you mark an interface as Comparable to itself, any correct implementation may only use methods from this interface to perform the comparison. Otherwise this relation can't be made anti-symmetric - a necessary condition to have a consistent ordering.

So think twice before marking an interface as comparable.

There is however a workaround in your case, if you are sure you are not mixing different implementations of your interface:

interface Foo {
}

interface Bar extends Foo, Comparable<Bar> {
}


class FooComparator<T extends Foo & Comparable<T>> implements Comparator<T> {

    @Override
    public int compare(T arg0, T arg1) {
        return arg0.compareTo(arg1);
    }
}

Comments

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.