Универсальная сопоставимая идиома Java

Я столкнулся со следующей частью определения универсального класса:

public class binarysearchnode<T extends Comparable<T>> implements Comparable<binarysearchnode<T>>{
.............
}

Пожалуйста, помогите объяснить, почему класс указывает себя в качестве параметра типа для сравнения при реализации сопоставимого интерфейса? Чем он будет отличаться от следующего:

public class binarysearchnode<T extends Comparable<T>> implements Comparable<? super (or extends)T>{
.............
}

person IUnknown    schedule 29.12.2012    source источник
comment
Потому что он сравним с другим экземпляром самого себя, а не с какой-то другой случайной вещью. Посмотрите на фактический метод compareTo(), и это должно быть ясно.   -  person Brian Roach    schedule 29.12.2012


Ответы (3)


Это позволяет сравнивать binarysearchnodes друг с другом. Если бы он реализовал Comparable<T>, это вместо этого означало бы, что узел можно сравнить с значением узла, что было бы странно.

Внутри класса вы, вероятно, найдете что-то вроде этого:

T value;

public int compareTo(binarysearchnode<T> other) {
   return value.compareTo(other.value);
}

Чтобы иметь возможность реализовать compareTo() таким образом, класс значений (T) должен быть сопоставим с другими объектами этого класса — отсюда и объявление <T extends Comparable<T>> в определении класса.

person Russell Zahniser    schedule 29.12.2012

Это потому, что автор класса хочет иметь возможность писать:

b1.compareTo(b2)

где b1 и b2binarysearchnode экземпляра. Разработчик также добавляет ограничение на T, чтобы T расширяло Comparable<T>. Вероятно, для того, чтобы реализация Comparable для binarysearchnode могла полагаться только на то, что экземпляры T сами являются Comparable.

В более общем смысле, хотя класс C1 может реализовать Comparable<C2>, в конечном счете, в этом нет смысла: это не означает, что экземпляр C2 может быть сравним с экземпляром C1. А из-за стирания типов было бы невозможно, например, для класса C1 реализовать оба Comparable<C1> и Comparable<C2>.

Кроме того, если бы binarysearchnode<T> реализовывал Comparable<T> напрямую, у вас было бы как минимум две проблемы:

  • вы бы не смогли сравнить один binarysearchnode<T> с другим;
  • учитывая экземпляр binarysearchnote<T> b и экземпляр T t, вы могли бы написать b.compareTo(t), но не t.compareTo(b) (поскольку T не реализует и не может реализовать Comparable<binarysearchnode<T>>), и это нарушает контракт Comparable.
person fge    schedule 29.12.2012

Допустим, у вас есть суперкласс A и подкласс B. Представьте, что суперкласс реализует Comparable<A>, тогда B также реализует Comparable<A> посредством наследования.

Ваш класс binarysearchnode объявлен как таковой:

public class binarysearchnode<T extends Comparable<T>>

не сможет принять B в качестве параметра типа для T (B не реализует Comparable<B>) Но когда он определен как таковой:

public class binarysearchnode<T extends Comparable<? super T>>

он сможет принимать B в качестве параметра типа для T, поскольку B реализует Comparable<A>, который выполняет Comparable<? super T>.

person bowmore    schedule 29.12.2012