В чем разница let, apply, with и also в Kotlin
Что проверяют
Знаете ли вы два различающих признака и умеете ли выбирать функцию по задаче, а не наугад.
Как отвечать
Все эти функции различаются ровно двумя вещами: как передаётся объект внутрь (аргументом it или получателем this) и что возвращается (результат лямбды или сам объект).
| Функция | Объект внутри | Возвращает |
|---|---|---|
let | it | результат лямбды |
run | this | результат лямбды |
with | this | результат лямбды |
apply | this | сам объект |
also | it | сам объект |
with отличается от run только формой: это не функция-расширение, объект передаётся первым аргументом.
Как выбирать по задаче:
applyдля настройки объекта, потому что возвращает его же:
val paint = Paint().apply { color = RED; isAntiAlias = true };
alsoдля побочного действия в середине цепочки, не ломающего её: записать в журнал, проверить, отдать в аналитику. Имяitтут удобнее, чемthis, потому что не затеняет внешний контекст;letдля преобразования и для безопасной работы с необязательным значением:
name?.let { greet(it) } выполнится только если значение есть;
runкогда нужно и обратиться к членам объекта, и вернуть результат;withкогда идёт серия обращений к одному объекту и результат не важен.
Практическое правило по читаемости: it предпочтительнее, когда объект передаётся дальше как аргумент, а this когда обращаетесь к его свойствам. Вложенные let внутри let быстро становятся нечитаемыми, и там лучше явные имена: let { user -> ... }.
Отдельно про ?.let: это не универсальная замена проверке на null. Для одной ветки он хорош, а для «иначе» лучше обычный if, потому что ?: run { } читается хуже.
Где спотыкаются
Не могут объяснить, чем apply отличается от also.
Используют let для настройки объекта и теряют его, возвращая результат последней строки.
Вкладывают несколько let подряд и путаются, к чему относится it.
Считают ?.let обязательной заменой проверке на null.