Відповіді:
У Котліні if
висловлювання - це вирази. Отже, наступний код еквівалентний:
if (a) b else c
Тут важлива різниця між виразом і твердженням. У Java / C # / JavaScript if
формує оператор, тобто це не відповідає значенню. Більш конкретно, ви не можете призначити його змінної.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
Якщо ви походите з мови, де if
є твердження, це може здатися неприродним, але це відчуття незабаром має вщухати.
when
.
x = a==b
b + if (a) c else d
проти b + (c if (a) else d)
останнього потрібні додаткові дужки. тому що c
не додається умовою і else
.
Ви можете визначити власну Boolean
функцію розширення, яка повертається, null
коли Boolean
має false
надати структуру, подібну до потрійного оператора:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Це зробило б a ? b : c
вираз перекладати так a then b ?: c
, як:
println(condition then "yes" ?: "no")
Оновлення. Але щоб зробити ще якийсь подібний Java перемикач, вам знадобиться щось подібне
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
зверніть увагу на лямбда. розрахунок його зміст має бути відкладено , поки ми не впевнені , condition
єtrue
Це виглядає незграбно, тому існує високий затребуваний запит для порту термінального оператора Java в Котлін
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
if (a) b else c
це те, що ви можете використовувати замість виразу потрійного оператора a ? b : c
.
У Котлін, багато керуючих оператори в тому числі if
, when
чи навіть try
можуть бути використані в якості вираження . Це означає, що вони можуть мати результат, який можна присвоїти змінній, повернутий з функції тощо.
В результаті виразів Котліна мова не дуже потрібна потрійному оператору .
if (a) b else c
це те, що ви можете використовувати замість виразу потрійного оператора a ? b : c
.
Я думаю, що ідея полягає в тому, що колишній вираз є більш читабельним, оскільки всі знають, що ifelse
робить, тоді ? :
як досить неясно, якщо ви вже не знайомі з синтаксисом.
Тим не менш, я повинен визнати, що я часто сумую за більш зручним оператором.
Інші альтернативи
коли
Ви також можете побачити when
конструкції, які використовуються в Котліні, коли перевіряються умови. Це також спосіб виразити каскади if-else альтернативним способом. Далі відповідає прикладу ОТ.
when(a) {
true -> b
false -> c
}
Розширення
Як показує багато хороших прикладів ( Котлінський термінальний умовний оператор ) в інших відповідях, розширення також можуть допомогти у вирішенні випадку використання.
Для себе я використовую такі функції розширення:
fun T?.or<T>(default: T): T = if (this == null) default else this
fun T?.or<T>(compute: () -> T): T = if (this == null) compute() else this
Перше поверне задане значення за замовчуванням у випадку, якщо об’єкт дорівнює нулю. Друга оцінить вираження, що надається лямбда в тому ж випадку.
Використання:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Особисто для мене код вище читаний, ніж if
конструкція накладки
e.getMessage() ?: "unknown"
. Другий може бути виражений якobj?.lastMessage?.timestamp ?: { Date() }()
Ява еквівалент потрійного оператора
a ? b : c
є простим ІФ в Котліні в одному рядку
if(a) b else c
немає потрійного оператора (умова? тоді: інше), тому що звичайний, якщо працює в цій ролі добре.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Особливий випадок для порівняння Null
можна скористатися оператором Elvis
if ( a != null ) a else b
// equivalent to
a ?: b
У kotlin немає потрійного оператора , оскільки if else
блок повертає значення
Отже, ви можете зробити:
val max = if (a > b) a else b
замість javamax = (a > b) ? b : c
Ми також можемо використовувати when
конструкцію, вона також повертає значення:
val max = when(a > b) {
true -> a
false -> b
}
Ось посилання на документацію kotlin: Control Flow: if, коли, for, while
У Котліна
if
- це вираз, тобто він повертає значення. Тому немає потрійного оператора(condition ? then : else)
, тому що звичайний, якщо працює в цій ролі добре. Посібник звідси
// Traditional usage
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// As expression
val max = if (a > b) a else b
Деякі кутові випадки, які не згадуються в інших відповідях.
Оскільки поява takeIf у Kotlin 1.1, потрійний оператор a ? b : c
також може бути виражений так:
b.takeIf { a } ?: c
Це стає ще коротшим у випадку, якщо c null
:
b.takeIf { a }
Також зауважте, що типова для Java value != null ? value : defaultValue
версія нульових перевірок, як переводити в ідеоматичний Котлін, просто value ?: defaultValue
.
Подібні a != null ? b : c
можна перекласти на a?.let { b } ?: c
.
b.takeIf { a } ?: c
коротше і читабельніше, ніж if (a) b else c
? Оператор Terneray, безумовно, відсутня функція в Котліні, оскільки імена змінних і умови можуть бути довгими і змусити вас розділити лінію, яка погана
takeIf
завжди оцінюється справжній випадок (тут a
). Цей вираз не тільки може бути марно обчислений, якщо a
трапиться помилковим, але ви не зможете отримати користь від розумних анкет à la if (a is Int) { a + 3 }
.
{ a }
є ліниво оціненою лямбда.
b
)". Але навіть { a }
, ледачи, треба оцінювати, щоб визначити результат вираження.
Java
int temp = a ? b : c;
Еквівалент Котліну:
var temp = if (a) b else c
ЗАВДАННЯ :
Розглянемо наступний приклад:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
У Котліні нам потрібен наступний еквівалент:
return (! answer.isSuccessful ())
?
"неправильний":
answer.body (). string ()
РІШЕННЯ :
1.а . Ви можете використовувати if-expression
в Котліні:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1б . Це може бути набагато краще, якщо ви перегорнете це if-expression
(давайте зробимо це без not
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . Оператор Етвіса Котліна ?:
може зробити роботу ще краще:
return answer.body()?.string() ?: "wrong"
3 . Або використовуйте Extension function
відповідний Answer
клас:
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . За допомогою Extension function
ви можете зменшити код завдяки Elvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . Або просто скористайтеся when
оператором:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Сподіваюсь, це допомагає.
коли замінює оператор комутатора мов C-подібних. У найпростішому вигляді це виглядає так
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when
як вислів, а не вираз. Більш релевантним порівнянням з потрійними умовними виразами було б, щоб кожна гілка повернула значення, таке, що ціле, коли вираз оцінюється до значення (як це відбувається з потрійними умовними умовами).
У Котліні немає потрійного оператора. Це здається проблематичним на перший погляд. Але подумайте, що ми можемо це зробити з inline, якщо інше твердження, тому що це тут вираження. Просто ми повинні зробити -
var number = if(n>0) "Positive" else "Negetive"
Тут ми можемо ще, якщо заблокувати занадто багато, скільки нам потрібно. Подібно до-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Отже, ця лінія настільки проста і набагато читає, ніж потрійний оператор. коли ми використовуємо більше ніж один потрійний оператор у Java, це здається жахливим. Але тут ми маємо чіткий синтаксис. навіть ми можемо записати його в декількох рядках.
Ви можете використовувати var a= if (a) b else c
замість термарного оператора.
Ще одна гарна концепція котліна - оператор Елвіса. Вам не потрібно перевіряти нуль кожен раз.
val l = b?.length ?: -1
Це поверне довжину, якщо b не є нульовим, інакше він виконує операцію правої сторони.
як цитується Дрю Ноакс, котлін використовує, якщо заява як вираз, тому термінальний умовний оператор більше не потрібен,
але з функцією розширення та перевантаження інфіксації ви могли це реалізувати самостійно, ось приклад
infix fun <T> Boolean.then(value: T?) = TernaryExpression(this, value)
class TernaryExpression<out T>(val flag: Boolean, val truly: T?) {
infix fun <T> or(falsy: T?) = if (flag) truly else falsy
}
тоді використовуйте його так
val grade = 90
val clazz = (grade > 80) then "A" or "B"
Ще одним цікавим підходом було б використання when
:
when(a) {
true -> b
false -> b
}
Це може бути досить зручно в деяких складніших сценаріях. І якщо чесно, для мене це читабельніше, ніжif ... else ...
Це можна зробити багатьма способами в Котліні
Використання if
if(a) b else c
Використання, коли
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
Нульова безпека
val a = b ?: c
У Котліні немає потрійної операції, але є кілька цікавих способів обійти це. Як зазначали інші, прямий переклад на Котлін виглядав би так:
val x = if (condition) result1 else result2
Але особисто я думаю, що це може трохи забитися і важко читати. Є деякі інші параметри, вбудовані в бібліотеку. Ви можете використовувати takeIf {} з оператором elvis:
val x = result1.takeIf { condition } ?: result2
Там відбувається те, що команда takeIf {} повертає або результат1, або нуль, а оператор elvis обробляє параметр null. Є, наприклад, кілька додаткових варіантів, наприклад {}:
val x = result1.takeUnless { condition } ?: result2
Мова зрозуміла, ви знаєте, що це робить.
Якщо це загальновживаний стан, ви також можете зробити щось цікаве, наприклад, використовувати метод вбудованого розширення. Припустимо, ми хочемо, наприклад, відстежувати рахунок гри як Int, і ми завжди хочемо повертати 0, якщо задана умова не виконується:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Гаразд, це здається некрасивим. Але врахуйте, як це виглядає при використанні:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
Як бачите, Kotlin пропонує велику гнучкість у тому, як ви вирішите висловити свій код. Існує незліченна кількість варіантів моїх прикладів, і, мабуть, способів, яких я ще не знайшов. Я сподіваюся, що це допомагає!
takeIf
дійсно мій улюблений варіант, дуже елегантний.
Пам'ятайте, що оператор Ternary та оператор Elvis мають у Котліні окремі значення, на відміну від багатьох популярних мов. Діяння expression? value1: value2
дасть вам погані слова від компілятора Kotlin , на відміну від будь-якої іншої мови, оскільки в Котліні немає термінального оператора, як згадується в офіційних документах . Причина в тому, що заяви if, коли і try-catch самі повертають значення.
Отже, дію expression? value1: value2
можна замінити на
val max = if (a> b) print ("Виберіть a") друку ("Select b")
Оператор Елвіса, який є у Котліна , працює лише у випадку змінних змінних, наприклад:
Якщо я роблю щось на кшталт
value3 = value1 ?: value2
того, якщо value1 є null, тоді value2 буде повернуто, інакше value1 буде повернуто.
Більш чітке розуміння можна досягти з цих відповідей .
Ви можете використовувати if
для цього вираз у Котліні. У Котліні if
- вираз із значенням результату. Тож у Котліні ми можемо писати
fun max(a: Int, b: Int) = if (a > b) a else b
і в Java ми можемо досягти того ж, але з більшим кодом
int max(int a, int b) {
return a > b ? a : b
}
Якщо ви не маєте для чого використовувати стандартні позначення, ви також можете створити / змоделювати його за допомогою infix із чимось подібним:
створити клас, щоб утримувати ціль та результат:
data class Ternary<T>(val target: T, val result: Boolean)
створити деякі функції інфіксації для імітації потрійної операції
infix fun <T> Boolean.then(target: T): Ternary<T> {
return Ternary(target, this)
}
infix fun <T> Ternary<T>.or(target: T): T {
return if (this.result) this.target else target
}
Тоді ви зможете використовувати його так:
val collection: List<Int> = mutableListOf(1, 2, 3, 4)
var exampleOne = collection.isEmpty() then "yes" or "no"
var exampleTwo = (collection.isNotEmpty() && collection.contains(2)) then "yes" or "no"
var exampleThree = collection.contains(1) then "yes" or "no"
Ще один короткий підхід до використання
val value : String = "Kotlin"
value ?: ""
Тут kotlin сам перевіряє нульове значення, і якщо воно є null, воно передає значення порожнього рядка.
Чому можна використовувати щось подібне:
when(a) {
true -> b
false -> b
}
коли ви можете реально використовувати щось подібне ( a
буле в даному випадку):
when {
a -> b
else -> b
}
? and :
суперечить декларування нуля / типу, а не перевірка типу. Крім цього я не бачу причин. Я думаю, що хтось напевно подумав би, якщо є вбудована перевірка стану if-else. Зачекаємо і подивимось у майбутніх версіях.
Під час роботи з Apply (), нехай здається дуже зручним при роботі з потрійними операціями, оскільки він більш елегантний і надасть вам місця
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
За допомогою наступних функцій infix я можу охопити багато випадків звичайного використання майже так само, як це можна зробити в Python:
class TestKotlinTernaryConditionalOperator {
@Test
fun testAndOrInfixFunctions() {
Assertions.assertThat(true and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(false and "yes" or "no").isEqualTo("no")
Assertions.assertThat("A" and "yes" or "no").isEqualTo("yes")
Assertions.assertThat("" and "yes" or "no").isEqualTo("no")
Assertions.assertThat(1 and "yes" or "no").isEqualTo("yes")
Assertions.assertThat(0 and "yes" or "no").isEqualTo("no")
Assertions.assertThat(Date() and "yes" or "no").isEqualTo("yes")
@Suppress("CAST_NEVER_SUCCEEDS")
Assertions.assertThat(null as Date? and "yes" or "no").isEqualTo("no")
}
}
infix fun <E> Boolean?.and(other: E?): E? = if (this == true) other else null
infix fun <E> CharSequence?.and(other: E?): E? = if (!(this ?: "").isEmpty()) other else null
infix fun <E> Number?.and(other: E?): E? = if (this?.toInt() ?: 0 != 0) other else null
infix fun <E> Any?.and(other: E?): E? = if (this != null) other else null
infix fun <E> E?.or(other: E?): E? = this ?: other
У Котліні немає потрійного оператора, найбільш закритими є два нижче випадки,
val a = true if(a) print("A is true") else print("A is false")
Якщо вираз зліва від ?: не є нульовим, оператор elvis повертає його, інакше він повертає вираз праворуч. Зауважте, що правий вираз оцінюється лише в тому випадку, якщо ліва частина є нульовою.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
приклад: var енергія: Int = дані? .get (позиція) ?. енергія? .toInt ()?: 0
У kotlin, якщо ви використовуєте ?: Він буде працювати, як якщо виписка повернеться до нуля, тоді ?: 0 знадобиться 0 або все, що у вас є, напишіть цю сторону.
У Котліні ви можете використовувати потрійну операцію так: val x = if(a) "add b" else "add c"
Після деяких досліджень інших ідей я отримав наступного потрійного оператора:
infix fun <T : Any> Boolean.yes(trueValue: T): T? = if (this) trueValue else null
infix fun <T : Any> T?.no(falseValue: T): T = this ?: falseValue
Приклад (запустіть тут ):
fun main() {
run {
val cond = true
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
run {
val cond = false
val result = cond yes "True!" no "False!"
println("ternary test($cond): $result")
}
}
Ця версія є вільною та не вступає в конфлікт з оператором зведення нуля.
then
замість yes
.