Наведіть приклади функцій, які демонструють коваріантність та протиріччя у випадках як перевантаження, так і перезавантаження в Java? [зачинено]


105

Покажіть, будь ласка, хороший приклад коваріації та протиріччя у Java.

Відповіді:


155

Коваріація:

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

Sub # getSomething є коваріантним, оскільки він повертає підклас типу повернення Super # getSomething (але повністю заповнює контракт Super.getSomething ())

Суперечність

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

Sub # doSomething є протилежним, оскільки він приймає параметр надкласу параметра Super # doSomething (але, знову ж таки, заповнює контракт Super # doSomething)

Зверніть увагу: цей приклад не працює на Java. Компілятор Java перевантажує і не замінить метод doSomething (). Інші мови підтримують цей стиль протиріччя.

Дженріки

Це також можливо для Generics:

List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;

Тепер ви можете отримати доступ до всіх методів, covariantListякі не приймають загальний параметр (оскільки він повинен бути чимось "розширює об'єкт"), але getters буде працювати нормально (так як повернутий об'єкт завжди буде типу "Object")

Навпаки це стосується contravariantList: Ви можете отримати доступ до всіх методів із загальними параметрами (ви знаєте, що це повинен бути надклас "String", тому ви завжди можете передавати його), але жодних отримувачів (тип, що повертається, може бути будь-якого іншого супертипу String )


79
Перший приклад протиріччя не працює на Java. doSomething () у підкласі - це перевантаження, а не переосмислення.
Крейг П. Мотлін

15
Справді. Java не підтримує противаріантні аргументи підтипу. Тільки коваріація щодо того, що стосується методу повернення типів (як у першому прикладі).
the_dark_destructor

Чудова відповідь. Коваріація мені здається логічною. Але ви могли б вказати мені на пункт JLS, який описує протиріччя? Чому викликається Sub.doSomething?
Михайло

2
Як зазначив Крейг, це не так. Я думаю, що тут відбувається зіткнення між перекриттям і перевантаженням, і SUN обрав (як завжди) варіант, сумісний із зворотним. Тож у Java ви не можете використовувати противаріантні параметри при переопределенні методу.
Твердо кодований

1
Вам би приємно знати, чому я отримую репутацію за свою відповідь.
Hardcoded

48

Ко-дисперсія: Ітерабел та Ітератор. Це майже завжди можна буде визначити спільний варіант Iterableабо Iterator. Iterator<? extends T>може використовуватися так само Iterator<T>- єдиним місцем, де з’являється параметр типу, є тип повернення з nextметоду, тому його можна безпечно передати на T. Але якщо у вас є Sрозширення T, ви також можете призначити Iterator<S>змінну типу Iterator<? extends T>. Наприклад, якщо ви визначаєте спосіб пошуку:

boolean find(Iterable<Object> where, Object what)

ви не зможете зателефонувати до цього List<Integer>і 5, тому його краще визначити як

boolean find(Iterable<?> where, Object what)

Контра-дисперсія: Компаратор. Це майже завжди має сенс використовувати Comparator<? super T>, оскільки його можна використовувати так само Comparator<T>. Параметр типу відображається лише як тип параметру compareметоду, тому Tйого можна безпечно передати. Наприклад, якщо у вас є, DateComparator implements Comparator<java.util.Date> { ... }і ви хочете сортувати сортування List<java.sql.Date>з цим компаратором ( java.sql.Dateце підклас java.util.Date), ви можете:

<T> void sort(List<T> what, Comparator<? super T> how)

але не з

<T> void sort(List<T> what, Comparator<T> how)

-4

Подивіться на принцип заміни Ліскова . Насправді, якщо клас B поширює клас A, то ви повинні мати можливість використовувати B, коли потрібен A.


6
Це не відповідає на питання і вводить в оману. Цілком можливо було б спроектувати варіантну систему, яка порушує семантичну коректність і тому порушує LSP.
Метт Віппл

це не так contra variant. super.doSomething("String")не вдалося замінити на sub.doSomething(Object).
цинк

Це не питання
Олів'єТеррієн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.