Параметры ограничивающего типа универсальных методов с интерфейсами?

Итак, у меня есть 2 версии одного и того же метода.

Версия 1:

public static <T> int countGreaterThan(T[] anArray, T elem) 
    {
        int count = 0; 
        for (T e : anArray)
        {
            if (e > elem)
                count++;
        }
        return count;
    }

Версия 2:

public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
    {
        int count = 0;
        for (T e : anArray)
        {
            if (e.compareTo(elem) > 0)
                count++;
        }
        return count;
    }

Eclipse жалуется на Версию 1, потому что оператор > можно использовать только при сравнении примитивов, что для меня имеет смысл.

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

Исходя из моего базового понимания интерфейсов, класс, реализующий интерфейс, должен предоставлять тело метода для каждого из методов, объявленных в интерфейсе.

Итак, почему Версия 2 не должна выглядеть вот так?

public int compareTo(T o)
    {
        //stuff for method body
    }


    public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem)
    {
        int count = 0;
        for (T e : anArray)
        {
            if (e.compareTo(elem) > 0)
                count++;
        }
        return count;
    }

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

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


Извините за путаницу, позвольте мне уточнить.

Вот код интерфейса Comparable:

public interface Comparable<T> {
   public int compareTo(T o);
     }

Для compareTo() нет тела метода, потому что это интерфейс. Почему мне не нужно вручную писать тело для compareTO(), чтобы я мог использовать интерфейс в моем методе countGreaterThan()?

Это потому, что интерфейс является частью Java Collections Framework (если это так, объясните, как это работает)

Вот другая ситуация, когда я создаю свой собственный интерфейс:

public interface Dance { //an interface
  public void boogie(int count);
}

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

public class theMoonwalk implements Dance {
  public void boogie(int count) {
    System.out.println("Slide " + count + " times!");
  }
  public void mJ() {
    System.out.println("Michael Jackson did this dance!");

}
public class theHustle implements Dance {
  public void boogie(int steps) {
    System.out.println("Step " + steps + " times!");
  }
}
public class theJitterBug implements Dance {
  public void boogie(int twists) {
    System.out.println("Twist " + twists + " times!");
  }
}

Почему мне не нужно писать тело метода для compareTo() (поскольку тело метода не включено в интерфейс Comparable для compareTo())?


person Patrick    schedule 02.06.2015    source источник
comment
Вы спрашиваете, почему вам не нужно писать метод public int compareTo(T o)?   -  person Oli    schedule 02.06.2015
comment
Я не понимаю. Класс, содержащий метод countGreaterThan, не должен реализовывать Comparable... Не могли бы вы пояснить, о чем вы здесь спрашиваете?   -  person aioobe    schedule 02.06.2015
comment
@Patrick Универсальный тип T должен реализовывать метод compareTo, а не класс, содержащий универсальный метод.   -  person James Buck    schedule 02.06.2015
comment
Это не дубликат.   -  person Oli    schedule 02.06.2015


Ответы (1)


Тип, на который в конечном итоге ссылается T, должен реализовывать Comparable<T>, а не класс, к которому вы объявляете привязанный тип.

Чтобы сделать это немного проще: чтобы использовать ваш метод countGreaterThan, любые объекты, содержащиеся в вашем массиве и в вашем аргументе elem, должны быть объектом Comparable.

Это означает, что допустим такой вызов:

Integer[] foo = {1, 2, 3, 4, 5};
YourClass.countGreaterThan(foo, 2);

Ваш тип привязан к Integer и Integer implements Comparable<Integer>.

Это не приемлемо:

Object[] bar = {new Object(), new Object(), new Object()};
YourClass.countGreaterThan(bar, new Object());

Ваш тип привязан к Object, а Object не реализует Comparable. Та же логика применима к пользовательскому объекту, который вы реализуете; если он не привязан к Comparable, то он не будет в правильной привязке.

person Makoto    schedule 02.06.2015