Ответы:
Вы можете использовать эту let
функцию следующим образом:
val a = b?.let {
// If b is not null.
} ?: run {
// If b is null.
}
Обратите внимание, что вам нужно вызывать run
функцию, только если вам нужен блок кода. Вы можете удалить run
-block, если у вас есть только одна строка после elvis-operator ( ?:
).
Имейте в виду, что run
блок будет оценен либо если b
равен нулю, либо если let
-block оценивается как null
.
Из-за этого обычно требуется просто if
выражение.
val a = if (b == null) {
// ...
} else {
// ...
}
В этом случае else
-block будет оцениваться, только если b
не равен нулю.
a
еще не определен в рамках let
и run
. Но вы можете получить доступ к значению b
внутри let
с помощью неявного параметра it
. Думаю, это служит той же цели.
a
перед этими блоками кода. И a
можно попасть внутрь.
a
? Если да b
, то it
служит той же цели. Переназначается ли a
с результатом val
-блока?
it
из let
блока. Результат блока let
или run
будет присвоен a
. Результатом будет последнее выражение в блоке. Вы можете использовать назначение после let
того, как / run
закончил, так же , как вы делаете с любым другим нормальным назначением.
Давайте сначала убедимся, что мы понимаем семантику предоставленной идиомы Swift:
if let a = <expr> {
// then-block
}
else {
// else-block
}
Это означает следующее: «если <expr>
результатом является необязательный параметр, then
отличный от nil, введите -блок с символом, a
привязанным к развернутому значению. В противном случае введите else
блок.
Особо обратите внимание, что a
это связано только с then
-block . В Котлине вы можете легко получить это, позвонив
<expr>?.also { a ->
// then-block
}
и вы можете добавить else
-блок следующим образом:
<expr>?.also { a ->
// then-block
} ?: run {
// else-block
}
Это приводит к той же семантике, что и идиома Swift.
Мой ответ полностью копирует других. Однако я не могу легко понять их выражение. Думаю, было бы неплохо дать более понятный ответ.
Быстро:
if let a = b.val {
//use "a" as unwrapped
}
else {
}
В Котлине:
b.val?.let{a ->
//use "a" as unwrapped
} ?: run{
//else case
}
let
вместо also
означает, что run
блок будет выполняться всякий раз, когда let
блок возвращается null
, а это не то, что мы хотим.
В отличие от Swift, необязательно разворачивать дополнительный компонент перед его использованием в Kotlin. Мы могли бы просто проверить, не является ли значение ненулевым, и компилятор отслеживает информацию о выполненной вами проверке и позволяет использовать ее как развернутую.
В Swift:
if let a = b.val {
//use "a" as unwrapped
} else {
}
В Котлине:
if b.val != null {
//use "b.val" as unwrapped
} else {
}
Обратитесь к документации: (нулевая безопасность) для получения дополнительных примеров использования
if let
заявление.Swift Optional Binding
(так называемый if-let
оператор) используется, чтобы узнать, содержит ли необязательный параметр значение, и если да, то сделать это значение доступным как временную константу или переменную. Итак, оператор Optional Binding
for if-let
выглядит следующим образом:
if-let
Заявление Свифта :
let b: Int? = 50
if let a = b {
print("Good news!")
} else {
print("Equal to 'nil' or not set")
}
/* RESULT: Good news! */
В Kotlin, как и в Swift, чтобы избежать сбоев, вызванных попыткой доступа к нулевому значению, когда это не ожидается, b.let { }
для правильного развертывания предоставляется специальный синтаксис (например, во втором примере) nullable types
:
Котлинский эквивалент 1
if-let
утверждения Свифта :
val b: Int? = null
val a = b
if (a != null) {
println("Good news!")
} else {
println("Equal to 'null' or not set")
}
/* RESULT: Equal to 'null' or not set */
let
Функция Kotlin при использовании в сочетании с оператором безопасного вызова ?:
предоставляет краткий способ обработки выражений, допускающих значение NULL.
Котлинский эквивалент 2 (функция Inline let и оператор Элвиса) оператора Swift
if-let
:
val b: Int? = null
val a = b.let { nonNullable -> nonNullable } ?: "Equal to 'null' or not set"
println(a)
/* RESULT: Equal to 'null' or not set */
guard let
заявление.guard-let
Оператор Swift прост и эффективен. Он проверяет наличие некоторого условия, и если оно оказывается ложным, else
выполняется инструкция, которая обычно завершает метод.
Давайте рассмотрим
guard-let
утверждение Swift :
let b: Int? = nil
func testIt() {
guard let a = b else {
print("Equal to 'nil' or not set")
return
}
print("Good news!")
}
testIt()
/* RESULT: Equal to 'nil' or not set */
Котлин, аналогичный эффекту
guard-let
заявления Свифта :
В отличие от Свифта, в Котлине нет никакого охранного заявления. Однако вы можете использовать Elvis Operator
- ?:
для получения аналогичного эффекта.
val b: Int? = 50
fun testIt() {
val a = b ?: return println("Equal to 'null' or not set")
return println("Good news!")
}
testIt()
/* RESULT: Good news! */
Надеюсь это поможет.
Вот как выполнить код, только если name
он не равен нулю:
var name: String? = null
name?.let { nameUnwrapp ->
println(nameUnwrapp) // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
println(nameUnwrapp) // printed "Alex"
}
let
делает, но вопрос заключается в else
стратегии, которая выполняется, если объект, для которого let
вызывается, является null
. Swift имеет его более естественным (спорного) способом. Но, сделав много работы как с Kotlin, так и с Swift, я действительно хочу, чтобы у Kotlin была простая распаковка, как у Swift.
Вот мой вариант, ограниченный очень распространенным случаем «if not null».
Прежде всего, определите это где-нибудь:
inline fun <T> ifNotNull(obj: T?, block: (T) -> Unit) {
if (obj != null) {
block(obj)
}
}
Наверное, так и должно быть internal
, чтобы не было конфликтов.
Теперь преобразуйте этот код Swift:
if let item = obj.item {
doSomething(item)
}
К этому коду Котлина:
ifNotNull(obj.item) { item ->
doSomething(item)
}
Обратите внимание, что, как всегда с блоками в Kotlin, вы можете отбросить аргумент и использовать it
:
ifNotNull(obj.item) {
doSomething(it)
}
Но если в блоке больше 1-2 строк, вероятно, лучше указать явно.
Это похоже на Swift, насколько я смог найти.
В kotlin есть аналогичный способ достичь стиля Swift if-let
if (val a = b) {
a.doFirst()
a.doSecond()
}
Вы также можете назначить несколько значений, допускающих значение NULL
if (val name = nullableName, val age = nullableAge) {
doSomething(name, age)
}
Такой подход будет более подходящим, если значения, допускающие значение NULL, используются более 1 раза. На мой взгляд, это помогает с точки зрения производительности, потому что значение, допускающее значение NULL, будет проверяться только один раз.
источник: Kotlin Discussion
Я добавляю этот ответ, чтобы прояснить принятый ответ, потому что он слишком велик для комментария.
Общий шаблон здесь заключается в том, что вы можете использовать любую комбинацию функций Scope, доступных в Kotlin, разделенных оператором Elvis, например:
<nullable>?.<scope function> {
// code if not null
} :? <scope function> {
// code if null
}
Например:
val gradedStudent = student?.apply {
grade = newGrade
} :? with(newGrade) {
Student().apply { grade = newGrade }
}
a
нельзя получить доступ внутрьlet
иrun
заблокировать.