Подробно разбираем популярные функции Kotlin

2
7415
Добавить в избранное

Продолжаем изучать полезные трюки, с которыми проще писать на языке Kotlin. В этой статье рассмотрим полезные функции Kotlin with() и withCorrectType().

Польза от использования with()

Предположим, мы не знакомы с функцией with(). Посмотрим, что написано в документации:

inline fun <T, R> with(receiver: T, block: T.() -> R): R (source)
Вызывает определенный функциональный блок с данным получателем в качестве аргумента и возвращает результат.

Если вам неизвестны определения блока и получателя, определение может показаться путанным. Давайте рассмотрим код, который все прояснит:

Первая строка описывает получатель (receiver) типа String. Внутри block можно применить любой метод на объект receiver без дополнительной классификации. И при этом в строке 9 Unit будет возвращен с типом функции block.

Таким образом работают block и receiver. Давайте на основе этого нового знания создадим более простой и нетипизированный пример:

Функция высшего порядка block передается в качестве последнего параметра функции with(). А благодаря этому, ее можно вынести за круглые скобки.

Так чем может быть полезна функция with() в коде? Ее часто можно использовать для замены классификаторов, вроде view.show() и view.hide() на уровне представления компонентов интерфейса:

Рефакторинг с помощью функции Kotlin withCorrectType()

Если вы сталкивались с ощущением, что что-то с вашим кодом не так, но не ясно что именно – это нормально. Давайте рассмотрим такой пример:

Очевидно, что MediaItemRenderer и IconItemRenderer имеют похожую логику метода render(). К тому же теперь мы знаем как избежать использования классификатора (view).

Теперь можно попробовать создать функцию аналогичную with() и переместить все проверки типов в нее.

Казалось бы, самое время отрефакторить функцию render(), вот только код не компилируется.

Kotlin compile error

Эта ошибка связана со стиранием общих типов и встречается в Java, ее описание есть в документации Oracle:

Во время процесса стирания типа, компилятор Java стирает все параметры типа и заменяет каждую свою первую привязку, если параметр типа ограничен, или объект, если параметр типа неограничен.

В Kotlin возможно избежать стирания дженерика T. Используя комбинацию ключевых слов inline и reified, мы можем легко этого избежать:

Можно пойти дальше и использовать IntelliJ IDEA Kotlin Bytecode, чтобы понять, что компилятор Kotlin делает с reified и как в этом помогает inline:

Компилятор Kotlin оставляет ваш тип, так как он отмечен в качестве reified, что невозможно без inline-функции, так как код withCorrentType() должен вставляться точно в местах вызова.

Хотите получать больше интересных материалов с доставкой?

Подпишитесь на нашу рассылку:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




Добавить комментарий