Общепринято, что дженерики Java не работают в некоторых важных аспектах. Комбинация подстановочных знаков и границ привела к некоторому серьезно нечитаемому коду.
Однако, когда я смотрю на другие языки, я действительно не могу найти систему универсальных типов, которой бы довольны программисты.
Если мы возьмем следующее в качестве целей проектирования такой системы типов:
- Всегда создает легко читаемые объявления типов
- Легко учиться (не нужно разбираться с ковариацией, контравариантностью и т. Д.)
- максимизирует количество ошибок во время компиляции
Есть ли язык, который понял это правильно? Если я гуглю, единственное, что я вижу, это жалобы на то, как система типов отстой в языке X. Эта сложность присуща универсальной типизации? Должны ли мы просто отказаться от попыток проверить безопасность типов на 100% во время компиляции?
Мой главный вопрос: какой язык «правильно понял» в отношении этих трех целей? Я понимаю, что это субъективно, но до сих пор я не могу найти ни одного языка, где не все его программисты сходятся во мнении, что система родовых типов - беспорядок.
Приложение: как уже отмечалось, сочетание подтипов / наследования и обобщений - вот что создает сложность, поэтому я действительно ищу язык, который сочетает в себе оба и избегает взрыва сложности.
источник
easy-to-read type declarations
? Третий критерий также неоднозначен: например, я могу превратить индекс массива из исключений границ в ошибки времени компиляции, не позволяя индексировать массивы, если я не смогу вычислить индекс во время компиляции. Кроме того, второй критерий исключает подтипы. Это не обязательно плохо, но вы должны знать, что вы спрашиваете.Foo<T> where SiameseCat:T
), и что нет возможности иметь дженерик, который не может быть преобразован вObject
. ИМХО, .NET выиграл бы от агрегатных типов, которые были бы похожи на структуры, но еще более скромны. Если быKeyValuePair<TKey,TValue>
был такой тип, тоIEnumerable<KeyValuePair<SiameseCat,FordFocus>>
можно было бы привести к немуIEnumerable<KeyValuePair<Animal,Vehicle>>
, но только если тип не может быть помещен в коробку.Ответы:
В то время как дженерики были основным направлением в сообществе функционального программирования на протяжении десятилетий, добавление дженериков к объектно-ориентированным языкам программирования создает некоторые уникальные проблемы, в частности взаимодействие подтипов и дженериков.
Однако, даже если мы сосредоточимся на объектно-ориентированных языках программирования, и в частности на Java, можно было бы разработать гораздо лучшую систему обобщений:
Универсальные типы должны быть допустимы везде, где есть другие типы. В частности, если
T
это параметр типа, следующие выражения должны компилироваться без предупреждений:Да, для этого требуется, чтобы дженерики были реализованы, как и любой другой тип языка
Ковариантность и контравариантность универсального типа должны быть указаны (или выведены из) его объявления, а не каждый раз, когда универсальный тип используется, поэтому мы можем написать
скорее, чем
Так как универсальные типы могут быть довольно длинными, нам не нужно указывать их избыточно. То есть мы должны уметь писать
скорее, чем
Любой тип должен быть допустим в качестве параметра типа, а не только ссылочных типов. (Если мы можем иметь
int[]
, почему мы не можем иметьList<int>
)?Все это возможно в C #.
источник
Использование подтипов создает много сложностей при выполнении общего программирования. Если вы настаиваете на использовании языка с подтипами, вы должны признать, что в общем программировании есть некоторая внутренняя сложность, которая сопровождает его. Некоторые языки делают это лучше, чем другие, но вы можете сделать это только до сих пор.
Сравните это с дженериками Хаскелла, например. Они достаточно просты, поэтому, если вы используете вывод типа, вы можете написать правильную обобщенную функцию случайно . В самом деле, если указать один тип, компилятор часто говорит себе: «Ну, я был собираюсь сделать это родовым, но вы попросили меня сделать это только для Интс, так что угодно.»
По общему признанию, люди используют систему типов Haskell поразительно сложными способами, делая ее проклятием каждого новичка, но сама система типов изящна и изящна и восхищается.
источник
a
должен быть целым числом».Примерно 20 лет назад было проведено немало исследований по объединению генериков с подтипами. Язык программирования Thor, разработанный исследовательской группой Барбары Лисков в Массачусетском технологическом институте, имел понятие «где», которое позволяет вам указывать требования типа, над которым вы параметризуетесь. (Это похоже на то, что C ++ пытается сделать с Концепциями .)
Документ, описывающий дженерики Тора и как они взаимодействуют с подтипами Тора: Day, M; Грубер, R; Лисков, Б; Майерс, AC: предложения « Подтипы и где»: ограничение параметрического полиморфизма , ACM Conf для Obj-Oriented Prog, Sys, Lang и Apps , (OOPSLA-10): 156-158, 1995.
Я полагаю, что они, в свою очередь, основаны на работе, которая была проделана на Изумруде в конце 1980-х годов. (Я не читал эту работу, но ссылка: Black, A; Hutchinson, N; Jul, E; Levy, H; Carter, L: Распределение и абстрактные типы в Emerald , _IEEE T. Software Eng., 13 ( 1): 65-76, 1987.
И Тор, и Изумруд были «академическими языками», поэтому они, вероятно, не получили достаточного использования, чтобы люди действительно могли понять, действительно ли пункты (концепции) действительно решают какие-либо реальные проблемы. Интересно прочитать статью Бьярна Страуструпа о том, почему первая попытка использования Concepts в C ++ не удалась: Stroustrup, B: Решение C ++ 0x «Удалить концепции» , доктор Доббс , 22 июля 2009 г. (Дополнительная информация на домашней странице Страуструпа . )
Другое направление, которое люди, кажется, пробуют - это то, что называется чертами . Например, язык программирования Mozilla Rust использует черты. Насколько я понимаю (что может быть совершенно неправильно), объявлять, что класс удовлетворяет признаку, очень похоже на то, что класс реализует интерфейс, но вы говорите «ведет себя как», а не как «является». Похоже, что новые языки программирования Swift от Apple используют аналогичную концепцию протоколов для определения ограничений параметров для обобщений .
источник