Продемонстрировать ковариацию и контравариантность на Java?

Пожалуйста, покажите хороший пример для ковариации и контравариантности на Java.

ковариации:

class Super { Object getSomething(){} } class Sub extends Super { String getSomething() {} } 

Sub # getSomething является ковариантным, потому что он возвращает подclass возвращаемого типа Super # getSomething (но полностью заполняет контракт Super.getSomething ())

контрвариация

 class Super{ void doSomething(String parameter) } class Sub extends Super{ void doSomething(Object parameter) } 

Sub # doSomething контравариантен, потому что он принимает параметр суперclassа параметра Super # doSomething (но, опять же, заполняет контракт Super # doSomething)

Обратите внимание: этот пример не работает в Java. Компилятор Java перегружает и не переопределяет doSomething () – Method. Другие языки поддерживают этот стиль контравариантности.

Дженерики

Это также возможно для Generics:

 List aList... List covariantList = aList; List contravariantList = aList; 

Теперь вы можете получить доступ ко всем методам covariantList которые не принимают общий параметр (поскольку это должно быть что-то «extends Object»), но getters будут работать нормально (поскольку возвращаемый объект всегда будет иметь тип «Object»)

Для contravariantList имеет значение обратное: вы можете получить доступ ко всем методам с помощью общих параметров (вы знаете, что это должен быть суперclass «String», поэтому вы всегда можете его перенести), но без геттеров (возвращаемый тип может быть любого другого супертипа String)

Соотношение: Итератор и Итератор. Практически всегда имеет смысл определить со-вариант Iterable или Iterator . Iterator Iterator может использоваться так же, как Iterator – единственное место, где появляется параметр типа – это тип возвращаемого значения из next метода, поэтому его можно безопасно поднять до T Но если у вас есть S extends T , вы также можете назначить Iterator переменной типа Iterator Iterator . Например, если вы определяете метод find:

 boolean find(Iterable where, Object what) 

вы не сможете вызвать его с помощью List и 5 , поэтому его лучше определить как

 boolean find(Iterable where, Object what) 

Контравариантность: компаратор. Практически всегда имеет смысл использовать Comparator Comparator , потому что он может использоваться как Comparator . Параметр type появляется только как тип параметра метода compare , поэтому T можно безопасно передать ему. Например, если у вас есть DateComparator implements Comparator { ... } и вы хотите отсортировать List с этим компаратором ( java.sql.Date является подclassом java.util.Date ), вы можете:

  void sort(List what, Comparator how) 

но не с

  void sort(List what, Comparator how) 

Посмотрите на принцип замещения Лискова . Фактически, если class B расширяет class A, тогда вы должны иметь возможность использовать B, когда требуется A.

Давайте будем гением компьютера.