Я просто собираюсь ответить на различия между декларацией-сайтом и дисперсией-сайтом использования, поскольку, хотя универсальные символы C # и Java отличаются во многих других отношениях, эти различия в основном ортогональны к дисперсии.
Прежде всегоЕсли я правильно помню, дисперсия использования сайта строго более мощная, чем дисперсия объявления сайта (хотя и ценой краткости), или, по крайней мере, символы подстановки Java (которые на самом деле более мощные, чем дисперсия использования сайта).Эта увеличенная мощность особенно полезна для языков, в которых интенсивно используются конструкции с сохранением состояния, таких как C # и Java (но Scala намного меньше, особенно потому, что его стандартные списки являются неизменяемыми).Рассмотрим List<E>
(или IList<E>
).Так как у него есть методы как для добавления E, так и для получения E, он инвариантен относительно E, и поэтому дисперсию на сайте декларации нельзя использовать.Однако при использовании дисперсии сайта использования вы можете просто сказать List<+Number>
, чтобы получить ковариантное подмножество List
и List<-Number>
, чтобы получить контравариантное подмножество List
.На языке объявления сайта разработчик библиотеки должен был бы создать отдельные интерфейсы (или классы, если вы разрешаете множественное наследование классов) для каждого подмножества, и List
расширяет эти интерфейсы.Если разработчик библиотеки не делает этого (обратите внимание, что IEnumerable
в C # выполняет только небольшое подмножество ковариантной части IList
), то вам не повезло, и вам придется прибегнуть к тем же хлопотам, которые нужно сделатьна языке без каких-либо различий.
Так что это преимущество наследования по сайту использования по сравнению с наследованием по сайту объявления.Преимущество наследования сайтов объявлений перед наследованием сайтов пользователей для пользователя является в основном лаконичным (при условии, что разработчик приложил усилия к тому, чтобы разделить каждый класс / интерфейс на его ковариантные и контравариантные части).Для чего-то вроде IEnumerable
или Iterator
хорошо не указывать ковариацию каждый раз, когда вы используете интерфейс.Java сделала это особенно раздражающим, используя длинный синтаксис (за исключением бивариантности, для которой решение Java в основном идеально).
Конечно, эти две языковые возможности могут сосуществовать.Для параметров типа, которые естественно ковариантны или контравариантны (например, в IEnumerable
/ Iterator
), объявите это в объявлении.Для параметров типа, которые естественно инвариантны (например, в (I)List
), объявляйте, какую дисперсию вы хотите использовать каждый раз, когда вы ее используете.Просто не указывайте дисперсию сайта использования для аргументов с декларацией сайта, так как это только сбивает с толку.
Существуют и другие более подробные проблемы, в которые я не вникал (например, как на самом деле подстановочные знаки)более мощный, чем вариация использования сайта), но я надеюсь, что это ответит на ваш вопрос к вашему контенту.Я признаю, что я склонен к отклонениям в использовании сайта, но я попытался описать основные преимущества, которые проявились в моих дискуссиях с программистами и исследователями языка.