Ну, просто, имеет ли смысл? Подумайте о замене Лискова.
ковариационной
Если A <: B
, имеет ли смысл передавать C[A]
там, где ожидается C[B]
? Если так, сделайте это C[+T]
. Классическим примером является неизменный List
, где List[A]
может быть передан всему, что ожидает List[B]
, при условии, что A
является подтипом B
.
Два контрпримера:
Изменяемые последовательности являются инвариантными, поскольку в противном случае возможны нарушения безопасности типов (фактически, ко-вариант Java Array
уязвим только для таких вещей, поэтому он инвариантен в Scala).
Неизменяемый Set
является инвариантным, хотя его методы очень похожи на методы неизменяемого Seq
. Разница заключается в contains
, который набирается на наборах и нетипизируется (т. Е. Принимает Any
) на последовательностях. Таким образом, даже при том, что в противном случае было бы возможно сделать его совместным, стремление к повышению безопасности типов для конкретного метода привело к выбору инвариантности по сравнению с ковариантностью.
Противопоказанием дисперсия
Если A <: B
, имеет ли смысл передавать C[B]
там, где ожидается C[A]
? Если так, сделайте это C[-T]
. Классический потенциальный пример - Ordering
. Хотя некоторые несвязанные технические проблемы не позволяют Ordering
быть противоположным, интуитивно понятно, что все, что может заказать суперкласс A
, может также заказать A
. Отсюда следует, что Ordering[B]
, который упорядочивает все элементы типа B
, супертипа A
, может быть передан чему-то ожидающему Ordering[A]
.
Хотя Ordering
в Scala не является противоположным вариантом, Scalaz Заказ является противоположным, как и ожидалось. Еще один пример из Scalaz - это его черта Equal .
Смешанная дисперсия?
Наиболее наглядным примером смешанной дисперсии в Scala является Function1
(и 2, 3 и т. Д.). Это противоречиво в параметре, который он получает, и ко-варианте в том, что он возвращает. Обратите внимание, что Function1
- это то, что используется для многих замыканий, а замыкания используются во многих местах, и в этих местах обычно Java использует (или будет использовать) классы Single Abstract Method.
Итак, если у вас есть ситуация, когда применяется класс SAM, это, скорее всего, место для смешанных противоречий и ковариаций.