Как вариативность места использования Java соотносится с вариативностью сайта объявления C#?

StackOverflow https://stackoverflow.com/questions/4231305

  •  26-09-2019
  •  | 
  •  

Вопрос

Насколько я понимаю, указание дисперсии для дженериков в С# происходит на уровне объявления типа:когда вы создаете универсальный тип, вы указываете дисперсию аргументов типа.В Java, с другой стороны, дисперсия указывается там, где используется общий:когда вы создаете переменную какого-либо универсального типа, вы указываете, как могут меняться ее аргументы типа.

Каковы плюсы и минусы каждого варианта?

Это было полезно?

Решение

Я просто собираюсь ответить на различия между декларационным сайтом и дисперсом на сайте использования, поскольку, когда C # и дженерики Java различаются во многих других способах, эти различия в основном ортогональны для дисперсии.

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

Так что это преимущества наследования сайта использования по наследству декларации-сайта. Преимущество декларационного наследования наследования сайта по наследству на месте использования в основном является в соответствии с пользователем (при условии, что дизайнер прошел усилие отделения каждого класса / интерфейса в его ковариантные и противоречие части). За что-то вроде IEnumerable или Iterator, Приятно не придется указывать ковариацию каждый раз, когда вы используете интерфейс. Java сделал это особенно раздражающим, используя длительный синтаксис (кроме бивариаце, для которого решение Java в основном идеально).

Конечно, эти два языковых функция могут сосуществовать. Для типа параметров, которые естественным образом ковариантны или контравариант (например, в IEnumerable/Iterator), объявите так в декларации. Для параметров типа, которые естественно инвариантны (например, в (I)List), заявляйте, какую дисперсию вы хотите каждый раз, когда вы его используете. Только не указывайте дисперсию на сайт для аргументов для аргументов с отклонением сайта декларации, так как просто делает вещи с толку.

Есть еще подробные проблемы, в которых я не перешел (например, как подстановочные знаки на самом деле более мощные, чем дисперсия на сайте), но я надеюсь, что это отвечает на ваш вопрос к вашему контенту. Я признаю, что я предвзятый к дисперсии на сайте использования, но я пытался изобразить основные преимущества обоих, которые придумали в моих дискуссиях с программистами и с языковыми исследователями.

Другие советы

Большинство людей, кажется, предпочитают декларационную дисперсию, потому что это облегчает пользователи из библиотеки (при этом немного сложнее для разработчика библиотеки, хотя я буду утверждать, что разработчик библиотеки должен думать о дисперсии независимо от того, где дисперсия на самом деле написана.)

Но имейте в виду, что ни Java, ни C # не являются примерами хорошего языкового дизайна.

Пока Джава Получил дисперсию правильно и работать независимо от JVM из-за совместимых улучшений VM в Java 5 и Type-Strasure, дисперсия на сайт использования делает использование немного громоздкой, и конкретная реализация типового стирания нарисована заслуженная критика.

C #Модель декларационного распределения сайта принимает бремя от пользователя библиотеки, но во время их введения обоснованных дженериков они в основном построили правила дисперсии в их виртуальную машину. Даже сегодня они не могут полностью поддерживать совместную контуру из-за этой ошибки (и не обратное совместимое введение классов сбора коробки с копиями, разделили программисты в два лагеря).

Это представляет собой сложное ограничение на все языки, ориентированные на CLR, и является одной из причин, по которой альтернативные языки программирования гораздо более живы на JVM, хотя кажется, что CLR имеет «гораздо приятные особенности».

Давайте посмотрим на Варенье: Scala - полностью объектно-ориентированный, функциональный гибрид, работающий на JVM. Они используют тип стирания типа, такие как Java, но и реализация дженериков, так и (Декларация-сайта), проще понимать, более простые и мощные, чем Java (или C #), потому что VM не налагает правила на то, как варьируется Работа. Scala Compiler проверяет обозначения дисперсионов и может отклонить неуходного исходного кода во время компиляции Вместо того, чтобы бросать исключения во время выполнения, в то время как полученные файлы .Class могут быть использованы в Java.

Одним из недостатков декларационной дисперсии сайта заключается в том, что в некоторых случаях кажется, что в некоторых случаях.

В то же время SCALA может использовать примитивные типы без бокса их в коллекциях, таких как в C #, используя @specialized Аннотация, которая сообщает Compiler Scala создать одну или несколько дополнительных реализаций класса или способа, специализирующегося на запрошенном примитивном типе.

SCALA также может «почти» воспитывать дженерики, используя манифесты, которые позволяют им получить универсальные типы во время выполнения, как в C #.

Недостатки дженериков в стиле Java

Одним из следствий является то, что версия Java работает только со ссылочными типами (или типами значений в штучной упаковке), а не типы значений. IMO Это самый большой недостаток, поскольку он предотвращает высокую производительность в много сценариев и требует ручного написания специализированных типов.

Он не гарантирует, что инвариантный, как «Этот список содержит только объекты типа X», и требует проверки времени выполнения на каждом добыче. Общий тип действительно существует.

При использовании отражения вы не можете задать экземпляр универсального объекта, который имеет общие параметры.

Преимущества дженериков стиля Java

Вы получаете дисперсию / можете отличить между различными универсальными параметрами.

Джава:Используйте дженерики отклонений на сайте, начиная с Java 5.Сломанные ковариантные массивы с другим синтаксисом, начиная с версии 1.0.Нет информации о типе времени выполнения дженериков.

С#:Используйте универсальные шаблоны отклонений на сайте, начиная с C# 2.0.Добавлено изменение сайта объявления в C# 4.0.Неработающие ковариантные массивы с синтаксисом, отличным от версии 1.0 (проблема идентична Java).«реифицированные» дженерики, означающие, что информация о типе не теряется во время компиляции.

Скала:Оба используют вариацию сайта/сайта объявления с ранних версий языка (по крайней мере, с 2008 года).Массивы не являются отдельной функцией языка, поэтому вы используете тот же синтаксис обобщений и правила изменения типов.Некоторые коллекции реализуются на уровне виртуальной машины с помощью массивов JVM, поэтому вы получаете равную или лучшую производительность во время выполнения по сравнению с кодом Java.

Подробно о проблеме безопасности типов массивов C#/Java:Вы можете привести Dog[] к Pet[] и добавить Cat и вызвать ошибку времени выполнения, которая не обнаруживается во время компиляции.Scala реализовала это правильно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top