Ответ
В Android работал с различными scope-функциями Kotlin, такими как let, run, with, apply и also.
let– для выполнения кода с объектом, возвращает результат лямбды.
user?.let { println(it.name) }
run– какlet, но с доступом к свойствам черезthis.
val length = "text".run { length }
with– аналогичноrun, но не extension-функция.
with(user) { println(name) }
apply– возвращает сам объект (this), удобен для инициализации.
val user = User().apply { name = "Alex" }
also– какapply, но принимает объект какit.
user.also { println("User: ${it.name}") }
Выбор зависит от контекста: let для null-проверок, apply/also для модификации, run/with для вычислений.
Ответ 18+ 🔞
Давай разберем эту тему, а то у некоторых от этих let и apply глаза на лоб лезут, как будто они впервые про this и it слышат. Всё проще, чем кажется, если не загоняться.
Смотри, в Kotlin есть такие штуки — scope-функции. По сути, это просто способы временно поиграть с объектом в своей песочнице. Их пять штук: let, run, with, apply и also. Выбор зависит от того, что ты хочешь сделать и что в итоге получить. Главное — не перепутать, а то получится пиздопроебибна вместо кода.
Вот краткая шпаргалка, чтобы не бздеть каждый раз:
-
let— Классика для работы с nullable. Объект внутри лямбды — этоit. Возвращает ты не сам объект, а результат последней строчки в лямбде. Идеально для цепочек проверок или преобразований.user?.let { println(it.name) } // Выведи имя, если user не nullТипа: «Эй, объект, если ты есть (
?), давай с тобой что-то сделаем и забудем». -
run— Почти какlet, но объект внутри — это ужеthis. Можно обращаться к его свойствам напрямую, безit.. Возвращает тоже результат лямбды. Часто используют для вычисления какого-то значения на основе объекта.val length = "text".run { length } // this.length, но this писать не надоУдивление пиздец, но иногда это читается лучше, чем
let. -
with— Старший, но не самый умный братrun. Не extension-функция, а принимает объект первым аргументом. Внутри лямбды объект — этоthis. Возвращает результат лямбды. Удобно, когда нужно много раз обращаться к свойствам одного объекта, чтобы не писать его имя каждый раз.with(user) { println(name) } // Всё равно что user.name, но короче -
apply— А вот это мой фаворит для настройки объектов. Внутри лямбды объект — этоthis, а возвращает он сам этот объект (this). Идеально, когда ты создал экземпляр и сразу хочешь ему накрутить свойств.val user = User().apply { name = "Alex" } // Настроил и вернул того же самого userКрасота! Создал, настроил — и поехал дальше. Волнение ебать от такой простоты.
-
also— Близнецapply, но с другим подходом. Объект внутри лямбды — этоit, а возвращает он опять же сам объект. Идеален для сайд-эффектов: логирования, отладки, каких-то промежуточных действий, когда тебе нужно и объект сохранить, и что-то с ним сделать.user.also { println("User: ${it.name}") } // Посмотрел, что внутри, и передал user дальше
Короче, чувак, выбор простой:
- Нужно проверить на null и что-то сделать? —
let. - Нужно создать и сразу настроить объект? —
apply. - Нужно что-то посчитать на основе объекта и получить результат? —
runилиwith. - Нужно объект и модифицировать, и вернуть, но при этом залогировать что-то? —
also.
Если начнёшь их все в одну кучу мешать бездумно, получится манда с ушами, которую потом сам не разберёшь. Пользуйся с умом, и код станет чище, а жизнь — проще.