реализация Comparable в интерфейсе - PullRequest
3 голосов
/ 18 октября 2010

Я вызываю определенный класс, используя только его интерфейс.Проблема в том, что сам класс реализует Comparable, но поскольку я ссылаюсь на класс через другой интерфейс, компилятор не знает, что он реализует Comparable.Я уверен, что есть простое решение для этого ... но я просто не могу думать об этом прямо сейчас.

Ответы [ 5 ]

8 голосов
/ 18 октября 2010

Будет ли Comparable<T> все , которое реализует интерфейс, также реализовывать *1003*?Если это так, я предлагаю вам просто расширить интерфейс Comparable<T>.

В противном случае вы можете просто привести к Comparable<T>, если вам случится узнать, что в этом случае он будет работать.Конечно, это теряет некоторую безопасность во время компиляции, но такова природа зверя.

1 голос
/ 18 октября 2010

Вы можете сделать несколько причудливых дженериков. Допустим, основным интерфейсом является Lickable (который определяет метод lick()), и вам нужен метод, который будет обрабатывать объекты, Lickable и Comparable. Вы пишете:

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

Затем вы можете вызывать это для объектов любого типа, которые Lickable и Comparable. Обратите внимание, что это работает только в том случае, если оба аргумента имеют тип, который является одновременно Lickable и Comparable. Если вы имеете в виду только один класс, то это должно быть хорошо. Вы можете столкнуться с ошибками компилятора, вызывающими мигрень, если использование этого метода усложняется.

1 голос
/ 18 октября 2010

Я бы предложил вам вместо этого использовать Comapartor. Вы можете использовать сортировку (список, компаратор). Ваша реализация компаратора преобразует класс в Comparable и использует его метод сравнения. Таким образом, компилятор будет удовлетворен, и вы снова будете использовать существующую реализацию метода сравнения.

1 голос
/ 18 октября 2010

Мне это кажется странным ... если у вас есть main, как показано ниже, вы можете заставить его работать с интерфейсом Parent и дочерними классами ниже ... но есть странность в том, что вы можете попытаться сравнить ChildA сChildB, который, вероятно, не имеет смысла делать.

Возможно, если бы вы намекнули, что делают классы / интерфейс, мы могли бы дать лучший ответ.

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.");
    }
}
0 голосов
/ 28 октября 2012

Сопоставимые интерфейсы сложны. В общем, если вы помечаете интерфейс как сопоставимый с самим собой, любая правильная реализация может использовать только методы из этого интерфейса для выполнения сравнения. В противном случае это отношение нельзя сделать антисимметричным - необходимое условие для согласованного упорядочения.

Так что подумайте дважды, прежде чем пометить интерфейс как сопоставимый.

Однако в вашем случае есть обходной путь, если вы уверены, что не смешиваете различные реализации вашего интерфейса:

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);
    }
}
...