Відповіді:
Ви можете використовувати 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
заблокувати.