tgoop.com/dev_easy_notes/230
Last Update:
На самом деле по большей части отличий довольно мало. Первое отличие синтаксическое ? super
заменили на in
, ? extends
заменили на out
:List<? extends Developer> developers = new ArrayList<MobileDeveloper>();
val developers: List<out Developer> = ArrayList<MobileDeveloper>();
List<? super Double> numbers = new ArrayList<Number>();
val numbers: List<in Double> = ArrayList<Number>();
Помимо этого теперь если у класса есть дженерик, мы не сможем создать объект этого класса без указания какого либо дженерика, как это было в Java. Это все довольно простые вещи, однако у дженериков в Kotlin есть два отличия, которые сильно все меняют.
Первое, теперь можно в объявлении класса указать ковариантность и контравариантность. Смотрите, в Java мы эти вещи могли указывать только на уровне ссылок. В Kotlin эту вещь упростили, и например если мы хотим ковариантность сразу на всех объектах нашего класса, достаточно в объявлении указать out возле дженерика. На практике это работает так:val numbers: List<Int> = listOf<Number>();
Видите в чем прикол. В Kotlin у List
дженерик помечен как out
на уровне интерфейса. Это автоматически дает свойство ковариантности всем объектам этого List. Аналогично работает и свойство контравариантности, для этого нужно поставить in
.
В предыдущем посте я писал про то, что свойство ковариантность и контравариантность накладывает ограничения на запись или чтение. В Kotlin эти ограничения сохраняются. И если вы в дженерике класса поставите out
, вы не сможете создать функцию в этом классе, такую, где дженерик был бы входным аргументом. То же самое и про in
, там ограничения на функции, где дженерик это возвращаемый тип.
Второе отличие, это возможность получить тип дженерика в runtime без регистрации, смс и рефлексии. В Kotlin ввели inline функции, т.е. функции, код которых встраивается в место использования. И вот, раз этот код будет заинлайнен, то по идее мы можем сразу узнать тип конкретного дженерика. Правда для этого нужно использовать ключевое слово reified
. inline fun <reified T : Any> fn() {
val kClass = T::class
println("Тип дженерика $kClass")
}
Подводя итог, основных отличия три: •
Нельзя создавать класс без указания дженерика •
Свойство ковариантность и контравариантность можно сразу задать всем объектам класса •
Через reified
можем получить тип дженерика в runtime
BY Dev Easy Notes
Share with your friend now:
tgoop.com/dev_easy_notes/230