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 if
dichiarazioni sono espressioni. Quindi il seguente codice è equivalente:
if (a) b else c
La distinzione tra espressione e affermazione è importante qui. In Java / C # / JavaScript, if
forma 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 d
vs. b + (c if (a) else d)
Quest'ultimo richiede parentesi aggiuntive. perché c
non è racchiuso dalla condizione e else
.
È possibile definire la propria Boolean
funzione di estensione che ritorna null
quando Boolean
deve false
fornire una struttura simile all'operatore ternario:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Ciò farebbe a ? b : c
tradurre un'espressione in questo a then b ?: c
modo:
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
, when
o persino try
possono 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 ifelse
fa, 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 when
costrutti 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 if
rivestimento 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 else
blocco restituisce valore
quindi, puoi fare:
val max = if (a > b) a else b
invece di javamax = (a > b) ? b : c
Possiamo anche usare la when
costruzione, 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 : c
può 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 : defaultValue
traducono in ideologico Kotlin in giusto value ?: defaultValue
.
Simile a != null ? b : c
può essere tradotto in a?.let { b } ?: c
.
b.takeIf { a } ?: c
più 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
takeIf
valuta sempre il caso vero (qui a
). Non solo quell'espressione può essere calcolata inutilmente se a
sembra 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-expression
in 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 function
per la Answer
classe 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' when
operatore:
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")
}
}
when
come 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 c
al 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 c
Usando quando
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
Sicurezza nulla
val a = b ?: c
Non 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: value2
ti 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: value2
può 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 ?: value2
allora se value1 è null allora value2 verrebbe restituito altrimenti value1 verrebbe restituito.
Una comprensione più chiara può essere raggiunta da queste risposte .
Puoi usare l' if
espressione 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.
then
invece di yes
.