Відповіді:
Ви можете використовувати let-функцію так:
val a = b?.let {
// If b is not null.
} ?: run {
// If b is null.
}
Зауважте, що runфункцію потрібно викликати лише в тому випадку, якщо вам потрібен блок коду. Ви можете видалити run-block, якщо у вас буде лише oneliner після оператора elvis ( ?:).
Майте на увазі, що runблок буде оцінено або, якщо він bє нульовим, або якщо let-block оцінюється до null.
Через це ти, як правило, хочеш просто ifвиразу.
val a = if (b == null) {
// ...
} else {
// ...
}
У цьому випадку else-блок буде оцінено лише у тому випадку, якщо bвін не є нульовим.
aще не визначено в межах letта run. Але ви можете отримати доступ до значення bвнутрішньої частини letза допомогою неявного параметра it. Це служить тій самій цілі, що і я гадаю.
aраніше цих блоків коду. І aможна отримати доступ всередину.
a? Якщо це так b, то itслужить точно такій самій цілі. Це перепризначення aрезультатом val-блока?
itз letблоку. Результат блоку letабо runблоку буде призначений a. Результат - останній вираз у блоці. Ви використовуєте завдання після let / runзакінчення, як і будь-яке інше звичайне завдання.
Спершу переконаємось, що ми розуміємо семантику поданої ідіоми Свіфта:
if let a = <expr> {
// then-block
}
else {
// else-block
}
Це означає це: "якщо <expr>результати не- thenнульові, необов'язково введіть -блок із символом, aприв'язаним до розпакованого значення. Інакше введіть elseблок.
Особливо зауважте, що aпов'язане лише в межах then-блока . У Котліні ви можете легко отримати це за телефоном
<expr>?.also { a ->
// then-block
}
і ви можете додати else-блок так:
<expr>?.also { a ->
// then-block
} ?: run {
// else-block
}
Це призводить до тієї ж семантики, що і ідіома Свіфта.
Моя відповідь - це повністю копія кота від інших. Однак я не можу легко зрозуміти їх вираз. Тож я гадаю, було б непогано надати більш зрозумілу відповідь.
Швидко:
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, не потрібно розгортати необов'язковий. Ми можемо просто перевірити, чи значення не є нульовим, і компілятор відслідковує інформацію про здійснену вами перевірку та дозволяє використовувати її як розкручену.
У Свіфті:
if let a = b.val {
//use "a" as unwrapped
} else {
}
У Котліні:
if b.val != null {
//use "b.val" as unwrapped
} else {
}
Додаткову документацію див . (Нульова безпека) для більшості таких випадків використання
if let заява.Swift's Optional Binding(так званий if-letоператор) використовується для з'ясування того, чи містить необов'язкове значення, і якщо так, щоб зробити це значення доступним у якості тимчасової постійної чи змінної. Отже, формулювання Optional Bindingдля 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! */
У Котліні, як і у 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Функція Котліна , коли використовується в поєднанні з оператором безпечного виклику ?:, забезпечує стислий спосіб обробляти нульові вирази.
Котлін еквівалент 2 (Inline let function та Elvis Operator) у
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вислів Свіфта :
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. Свіфт має це більш природним (суперечливим) способом. Але багато зробив Котліна та Свіфта, я б хотів, щоб у Котліна було просте розгортання, як це робив Свіфт.
Ось мій варіант, обмежений дуже поширеним випадком "якщо не нульовим".
Перш за все, визначте це десь:
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)
}
Зауважте, що як завжди з блоками в Котліні, ви можете кинути аргумент і використовувати it:
ifNotNull(obj.item) {
doSomething(it)
}
Але якщо в блоці більше 1-2 рядків, мабуть, найкраще бути явним.
Це настільки ж схоже на Свіфт, як я міг знайти.
У котліні є подібний спосіб досягти стилю Свіфта, якщо нехай
if (val a = b) {
a.doFirst()
a.doSecond()
}
Можна також призначити кілька нульових значень
if (val name = nullableName, val age = nullableAge) {
doSomething(name, age)
}
Такий підхід буде більш підходящим, якщо нульові значення використовуються більше 1 разу. На мою думку, це допомагає в аспекті продуктивності, оскільки нульове значення буде перевірено лише один раз.
джерело: Обговорення Котліна
Я додаю цю відповідь, щоб уточнити прийняту відповідь, оскільки вона занадто велика для коментаря.
Загальна закономірність тут полягає в тому, що ви можете використовувати будь-яку комбінацію функцій діапазону, доступних у Котліні, розділених Оператором Елвіса, як це:
<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заблокувати.