Как определить дисперсию параметра типа? - PullRequest
11 голосов
/ 12 марта 2011

Вдохновленный Реальные примеры совместной и контравариантности в Scala Я подумал, что лучшим вопросом будет:

При проектировании библиотеки, есть ли конкретный набор вопросов, которые вы должны задать себе при определении, должен ли параметр типа быть ковариантным или контравариантным? Или вы должны сделать все инвариантным, а затем изменить при необходимости?

1 Ответ

16 голосов
/ 12 марта 2011

Ну, просто, имеет ли смысл? Подумайте о замене Лискова.

ковариационной

Если 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, это, скорее всего, место для смешанных противоречий и ковариаций.

...