Материал про использование let я увидел на канале Android Live, а оригинальная статья вот.
Не вижу смысла переводить всю статью, так как пост на канале сделал отличную выжимку. А я просто добавлю отсебятины.
Для начала let. Это шикарно. С null безопасным Kotlin просто невозможно не знать эту специальную функцию, которая будет выполнена только в случае, если переменная…собственно не null.
Но как показывает автор статьи, иногда есть более подходящие решения для некоторых случаев и бездумно летить всё подряд тоже не нужно.
Итак, когда лучше не использовать let
⭕️ для проверки на null immutable переменной. Я полностью согласен, что a?.let { foo(a) } симпатичнее, но она генерирует лишнюю переменную в байткоде, в отличии от аналога if not null. Вряд ли вы заметите огромную разницу, но если можно избежать создания лишней переменной, то почему бы этого не сделать.
⭕️ для использования переменных только внутри let лучше использовать run, который освободит нас от личшних it. Например, мы хотим что-то сделать с webView:
1 2 3 4 5 6 7 8 |
webviewSetting?.let { it.javaScriptEnabled = true it.databaseEnabled = true } webviewSetting?.run { javaScriptEnabled = true databaseEnabled = true } |
⭕️ если хотите передать переменную дальше по цепочке. Например, если вы хотите указать размер списка, если он не null, а дальше что-то продолжить делать с ним. Альтернативным решением будет использование also, хотя это тоже не идеальное решение (так как там тоже будет несколько ?).
1 2 3 4 5 6 7 8 9 |
// НЕТ stringList?.let { println("Total Count: ${it.size}") it }?.forEach{ println(it) } // ТОЖЕ НЕТ, НО ЛУЧШЕ stringList?.also { println("Total Count: ${it.size}") }?.forEach{ println(it) } |
Когда же тогда использовать let
🟢 для проверки на null mutable переменной. Тут хорошо подходит let, так как он избавляет нас от дополнительного ? (а он может задолбать) при взаимодействии с переменной.
1 2 3 4 5 |
private var str: String? = null fun process() { str?.let { /*Do something*/ } } |
🟢 если хотите использовать переменную снаружи от let. Например, если вы хотите проициализировать другие переменные тем классом, что был у вас:
1 2 3 4 5 6 7 |
var javaScriptEnabled = false var databaseEnabled = false webviewSetting?.let { javaScriptEnabled = it.javaScriptEnabled databaseEnabled = it.databaseEnabled } |
Это удобнее для review кода, чем функция run. Впрочем и run может подойти, если имена будут с какими-то префиксами или вроде того.
🟢 когда у вас есть проверка из цепочки ?
. Например:
1 2 3 4 5 6 7 |
return string?.asIterable()?.distinct()?.sorted() генерирует больше байткода, чем: return string?.let { it.asIterable().distinct().sorted() } |
Итак. LET удобный инструмент, но у него есть более удобные для некоторых случаев альтернативы, и его тоже нужно использовать с умом.
Спасибо!