Qual è l'equivalente di questa espressione in Kotlin?
a ? b : c
Questo non è un codice valido in Kotlin.
Qual è l'equivalente di questa espressione in Kotlin?
a ? b : c
Questo non è un codice valido in Kotlin.
Risposte:
In Kotlin, le ifdichiarazioni sono espressioni. Quindi il seguente codice è equivalente:
if (a) b else c
La distinzione tra espressione e affermazione è importante qui. In Java / C # / JavaScript, ifforma un'istruzione, il che significa che non si risolve in un valore. Più concretamente, non è possibile assegnarlo a una variabile.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
Se provieni da una lingua in cui ifè presente un'affermazione, questo potrebbe sembrare innaturale, ma questa sensazione dovrebbe presto placarsi.
when.
x = a==b
b + if (a) c else dvs. b + (c if (a) else d)Quest'ultimo richiede parentesi aggiuntive. perché cnon è racchiuso dalla condizione e else.
È possibile definire la propria Booleanfunzione di estensione che ritorna nullquando Booleandeve falsefornire una struttura simile all'operatore ternario:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Ciò farebbe a ? b : ctradurre un'espressione in questo a then b ?: cmodo:
println(condition then "yes" ?: "no")
Aggiornamento: ma per fare un po 'più di interruttore condizionale simile a Java avrai bisogno di qualcosa del genere
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
presta attenzione alla lambda. il calcolo contenuto dovrebbe essere rimandata fino a quando ci assicuriamo che conditionètrue
Questo sembra goffo, ecco perché esiste una richiesta molto richiesta per il porting dell'operatore ternario Java in Kotlin
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
?:operatore qui è elvis-operator: kotlinlang.org/docs/reference/null-safety.html#elvis-operator
if (a) b else c
è quello che puoi usare invece dell'espressione dell'operatore ternario a ? b : c.
In Kotlin, molte espressioni di controllo incluse if, wheno persino trypossono essere usate come espressioni . Ciò significa che quelli possono avere un risultato che può essere assegnato a una variabile, restituito da una funzione ecc.
Come risultato delle espressioni di Kotlin, la lingua non ha davvero bisogno dell'operatore ternario .
if (a) b else c
è quello che puoi usare invece dell'espressione dell'operatore ternario a ? b : c.
Penso che l'idea sia che l'espressione precedente sia più leggibile poiché tutti sanno cosa ifelsefa, mentre non ? :è abbastanza chiaro se non si ha già familiarità con la sintassi.
Tuttavia, devo ammettere che spesso mi manca l'operatore ternario più conveniente.
Altre alternative
quando
Potresti anche vedere whencostrutti usati in Kotlin quando le condizioni sono controllate. È anche un modo per esprimere le cascate if-else in modo alternativo. Quanto segue corrisponde all'esempio di OT.
when(a) {
true -> b
false -> c
}
estensioni
Come molti buoni esempi ( Operatore condizionale ternario di Kotlin ) nelle altre risposte mostrano, le estensioni possono anche aiutare a risolvere il tuo caso d'uso.
Per quanto mi riguarda, utilizzo le seguenti funzioni di estensione:
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
Il primo restituirà il valore predefinito fornito nel caso in cui l'oggetto sia uguale a null. Il secondo valuterà l'espressione fornita in lambda nello stesso caso.
Uso:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Personalmente per me il codice sopra è più leggibile rispetto al ifrivestimento interno
e.getMessage() ?: "unknown". Il secondo può essere espresso comeobj?.lastMessage?.timestamp ?: { Date() }()
Equivalente di Java dell'operatore ternario
a ? b : c
è un semplice IF in Kotlin in una riga
if(a) b else c
non esiste un operatore ternario (condizione? allora: altro), perché ordinario se funziona bene in questo ruolo.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Caso speciale per il confronto null
puoi usare l' operatore Elvis
if ( a != null ) a else b
// equivalent to
a ?: b
Non esiste alcun operatore ternario in kotlin, poiché il if elseblocco restituisce valore
quindi, puoi fare:
val max = if (a > b) a else b
invece di javamax = (a > b) ? b : c
Possiamo anche usare la whencostruzione, che restituisce anche valore:
val max = when(a > b) {
true -> a
false -> b
}
Ecco il link per la documentazione di kotlin: Flusso di controllo: if, when, for, while
In Kotlin,
ifè un'espressione, ovvero restituisce un valore. Pertanto non esiste un operatore ternario(condition ? then : else), perché ordinario se funziona bene in questo ruolo. fonte manuale da qui
// 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
Alcuni casi d'angolo non menzionati in altre risposte.
Dall'apparizione di takeIf in Kotlin 1.1 l'operatore ternario a ? b : cpuò anche essere espresso in questo modo:
b.takeIf { a } ?: c
Questo diventa ancora più breve nel caso in cui c sia null:
b.takeIf { a }
Nota anche che nel mondo Java i controlli null come value != null ? value : defaultValuetraducono in ideologico Kotlin in giusto value ?: defaultValue.
Simile a != null ? b : cpuò essere tradotto in a?.let { b } ?: c.
b.takeIf { a } ?: cpiù breve e più leggibile di if (a) b else c? L'operatore di Terneray è certamente una caratteristica mancante in Kotlin poiché i nomi delle variabili e la condizione possono essere lunghi e farti dividere la linea che è male
takeIfvaluta sempre il caso vero (qui a). Non solo quell'espressione può essere calcolata inutilmente se asembra essere falsa, ma non puoi beneficiare di cast intelligenti if (a is Int) { a + 3 }.
{ a }è una lambda pigramente valutata.
b)". Ma anche { a }, sebbene pigro, deve essere valutato per determinare il risultato dell'espressione.
Giava
int temp = a ? b : c;
Equivalente a Kotlin :
var temp = if (a) b else c
COMPITO :
Consideriamo il seguente esempio:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
Abbiamo bisogno del seguente equivalente in Kotlin:
return (! answer.isSuccessful ())
?"wrong":answer.body (). string ()
SOLUZIONI :
1.a . Puoi usare if-expressionin Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.B . Può essere molto meglio se capovolgi questo if-expression(facciamolo senza not):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . L'operatore Elvis di Kotlin ?:può fare un lavoro ancora meglio:
return answer.body()?.string() ?: "wrong"
3 . Oppure usa un Extension functionper la Answerclasse corrispondente :
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . Usando Extension functionè possibile ridurre un codice grazie a Elvis operator:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . O semplicemente usa l' whenoperatore:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Spero che sia di aiuto.
quando sostituisce l'operatore switch di linguaggi di tipo C. Nella forma più semplice sembra così
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
whencome un'istruzione, non un'espressione. Un confronto più pertinente con le espressioni condizionali ternarie sarebbe di fare in modo che ciascun ramo restituisca un valore, in modo tale che l'intera espressione quando valuti un valore (come accade con i condizionali ternari).
Non esiste un operatore ternario a Kotlin. Sembra problematico a prima vista. Ma pensa che possiamo farlo con un'istruzione if else inline perché questa è espressione qui. Semplicemente dobbiamo fare -
var number = if(n>0) "Positive" else "Negetive"
Qui possiamo altro se bloccare troppi quanti ne abbiamo bisogno. Piace-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Quindi questa linea è così semplice e molto leggibile rispetto all'operatore ternario. quando usiamo più di un operatore ternario in Java sembra orribile. Ma qui abbiamo una sintassi chiara. anche noi possiamo scriverlo anche su più righe.
È possibile utilizzare var a= if (a) b else cal posto dell'operatore ternario.
Un altro buon concetto di kotlin è l'operatore Elvis. Non è necessario controllare null ogni volta.
val l = b?.length ?: -1
Questo restituirà la lunghezza se b non è null, altrimenti esegue l'istruzione sul lato destro.
come citato da Drew Noakes, kotlin usa if come espressione, quindi Ternary Conditional Operator non è più necessario,
ma con la funzione di estensione e il sovraccarico infisso, potresti implementarlo da solo, ecco un esempio
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
}
quindi usalo in questo modo
val grade = 90
val clazz = (grade > 80) then "A" or "B"
Un altro approccio interessante sarebbe quello di utilizzare when:
when(a) {
true -> b
false -> b
}
Può essere abbastanza utile in alcuni scenari più complessi. E onestamente, è più leggibile per me cheif ... else ...
Puoi farlo in molti modi a Kotlin
Usando if
if(a) b else cUsando quando
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}Sicurezza nulla
val a = b ?: cNon esiste un'operazione ternaria a Kotlin, ma ci sono alcuni modi divertenti per aggirare questo. Come altri hanno sottolineato, una traduzione diretta in Kotlin sarebbe simile a questa:
val x = if (condition) result1 else result2
Ma, personalmente, penso che possa essere un po 'ingombra e difficile da leggere. Ci sono alcune altre opzioni integrate nella libreria. Puoi usare takeIf {} con un operatore elvis:
val x = result1.takeIf { condition } ?: result2
Quello che sta succedendo lì è che il comando takeIf {} restituisce il risultato1 o null e l'operatore elvis gestisce l'opzione null. Ci sono alcune opzioni aggiuntive, takeUnless {}, ad esempio:
val x = result1.takeUnless { condition } ?: result2
La lingua è chiara, sai cosa sta facendo.
Se è una condizione comunemente usata, potresti anche fare qualcosa di divertente come usare un metodo di estensione in linea. Supponiamo di voler monitorare un punteggio di gioco come Int, ad esempio, e vogliamo sempre restituire 0 se una determinata condizione non è soddisfatta:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Ok, sembra brutto. Ma considera come appare quando viene utilizzato:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
Come puoi vedere, Kotlin offre molta flessibilità nel modo in cui scegli di esprimere il tuo codice. Ci sono innumerevoli varianti dei miei esempi e probabilmente modi che non ho ancora scoperto. Spero che questo possa essere d'aiuto!
takeIfè davvero la mia opzione preferita, molto elegante.
Ricorda che l' operatore ternario e l' operatore Elvis hanno significati separati in Kotlin, a differenza di molte lingue popolari. Fare expression? value1: value2ti darebbe parolacce dal compilatore di Kotlin , a differenza di qualsiasi altra lingua in quanto non esiste un operatore ternario a Kotlin come menzionato nei documenti ufficiali . Il motivo è che le stesse istruzioni if, when e try-catch restituiscono valori.
Quindi, fare expression? value1: value2può essere sostituito da
val max = if (a> b) print ("Scegli a") else print ("Scegli b")
L' operatore Elvis che Kotlin ha, funziona solo nel caso di variabili nullable es .:
Se faccio qualcosa del genere,
value3 = value1 ?: value2allora se value1 è null allora value2 verrebbe restituito altrimenti value1 verrebbe restituito.
Una comprensione più chiara può essere raggiunta da queste risposte .
Puoi usare l' ifespressione per questo in Kotlin. In Kotlin ifè un'espressione con un valore di risultato. Quindi in Kotlin possiamo scrivere
fun max(a: Int, b: Int) = if (a > b) a else b
e in Java possiamo ottenere lo stesso ma con un codice più grande
int max(int a, int b) {
return a > b ? a : b
}
Se non fai cosa usare la notazione standard puoi anche crearla / simularla usando infix con qualcosa del genere:
crea una classe per mantenere il tuo obiettivo e il risultato:
data class Ternary<T>(val target: T, val result: Boolean)
creare alcune funzioni infix per simulare un'operazione ternaria
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
}
Quindi sarai in grado di usarlo in questo modo:
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"
Un altro breve approccio da usare
val value : String = "Kotlin"
value ?: ""
Qui kotlin stesso controlla un valore nullo e se è nullo passa un valore stringa vuoto.
Perché uno dovrebbe usare qualcosa del genere:
when(a) {
true -> b
false -> b
}
quando puoi effettivamente usare qualcosa del genere ( aè booleano in questo caso):
when {
a -> b
else -> b
}
? and :contraddizione con la dichiarazione nullable / type piuttosto che un controllo del tipo. A parte ciò, non vedo alcun motivo. Penso che qualcuno avrebbe sicuramente pensato, se ci fosse un controllo di condizione if-else in linea. Aspettiamo e vediamo nelle versioni future.
Quando lavori con apply (), ti sembra molto utile quando gestisci operazioni ternarie, poiché è più elegante e ti dà spazio
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
Con le seguenti funzioni infix posso trattare molti casi d'uso più o meno allo stesso modo in cui può essere fatto in 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
Non esiste un operatore ternario a Kotlin, i più chiusi sono i due casi seguenti,
val a = true if(a) print("A is true") else print("A is false")
Se l'espressione a sinistra di?: Non è nulla, l'operatore elvis la restituisce, altrimenti restituisce l'espressione a destra. Si noti che l'espressione del lato destro viene valutata solo se il lato sinistro è nullo.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
esempio: var energy: Int = data? .get (position) ?. energy? .toInt ()?: 0
In kotlin se stai usando ?: Funzionerà come se l'istruzione restituirà null allora ?: 0 ci vorrà 0 o qualunque cosa tu abbia scritto da questo lato.
In Kotlin puoi usare l'operazione ternaria in questo modo: val x = if(a) "add b" else "add c"
Dopo alcune ricerche su altre idee, ho derivato il seguente operatore ternario:
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
Esempio (esegui qui ):
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")
}
}
Questa versione è fluente e non è in conflitto con l'operatore di coalescenza nulla.
theninvece di yes.