¿Cuál es el equivalente de esta expresión en Kotlin?
a ? b : c
Este no es un código válido en Kotlin.
¿Cuál es el equivalente de esta expresión en Kotlin?
a ? b : c
Este no es un código válido en Kotlin.
Respuestas:
En Kotlin, las if
declaraciones son expresiones. Entonces el siguiente código es equivalente:
if (a) b else c
La distinción entre expresión y declaración es importante aquí. En Java / C # / JavaScript, if
forma una declaración, lo que significa que no se resuelve en un valor. Más concretamente, no puede asignarlo a una variable.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
Si vienes de un idioma donde if
hay una declaración, esto puede parecer antinatural, pero ese sentimiento debería desaparecer pronto.
when
.
x = a==b
b + if (a) c else d
vs. b + (c if (a) else d)
El último requiere paréntesis adicionales. porque c
no está encerrado por la condición y else
.
Puede definir su propia Boolean
función de extensión que se devuelve null
cuando Boolean
es false
proporcionar una estructura similar al operador ternario:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
Esto haría que una a ? b : c
expresión se traduzca a a then b ?: c
, así:
println(condition then "yes" ?: "no")
Actualización: Pero para hacer un cambio condicional más similar a Java, necesitará algo así
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
Presta atención a la lambda. su cálculo de contenido debe posponerse hasta que nos aseguremos de que condition
seatrue
Este parece torpe, es por eso que existe una gran demanda para portar el operador ternario de Java a Kotlin
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
?:
operador aquí es elvis-operator
: kotlinlang.org/docs/reference/null-safety.html#elvis-operator
if (a) b else c
es lo que puede usar en lugar de la expresión del operador ternario a ? b : c
.
En Kotlin, muchas declaraciones de control incluyen if
, when
o incluso try
se pueden usar como expresiones . Esto significa que esos pueden tener un resultado que puede asignarse a una variable, devolverse de una función, etc.
Como resultado de las expresiones de Kotlin, el lenguaje no necesita realmente el operador ternario .
if (a) b else c
es lo que puede usar en lugar de la expresión del operador ternario a ? b : c
.
Creo que la idea es que la expresión anterior es más legible ya que todos saben qué ifelse
hace, mientras no ? :
está claro si aún no está familiarizado con la sintaxis.
Sin embargo, debo admitir que a menudo extraño el operador ternario más conveniente.
Otras alternativas
cuando
También puede ver when
construcciones utilizadas en Kotlin cuando se verifican las condiciones. También es una forma de expresar cascadas if-else en una forma alternativa. Lo siguiente corresponde al ejemplo de OT.
when(a) {
true -> b
false -> c
}
Extensiones
Como muestran muchos buenos ejemplos ( Operador condicional ternario de Kotlin ) en las otras respuestas, las extensiones también pueden ayudarlo a resolver su caso de uso.
Para mí uso las siguientes funciones de extensión:
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
El primero devolverá el valor predeterminado proporcionado en caso de que el objeto sea igual a nulo. El segundo evaluará la expresión proporcionada en lambda en el mismo caso.
Uso:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Personalmente, para mí, el código anterior es más legible que la if
construcción en línea
e.getMessage() ?: "unknown"
. El segundo puede expresarse comoobj?.lastMessage?.timestamp ?: { Date() }()
El equivalente de Java del operador ternario
a ? b : c
es un IF simple en Kotlin en una línea
if(a) b else c
no hay operador ternario (condición? entonces: más), porque ordinario si funciona bien en este rol.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Caso especial para comparación nula
puedes usar el operador de Elvis
if ( a != null ) a else b
// equivalent to
a ?: b
No hay operador ternario en kotlin, ya que el if else
bloque devuelve valor
entonces, puedes hacer: en
val max = if (a > b) a else b
lugar de Javamax = (a > b) ? b : c
También podemos usar when
construcción, también devuelve valor:
val max = when(a > b) {
true -> a
false -> b
}
Aquí hay un enlace para la documentación de kotlin: Flujo de control: if, when, for, while
En Kotlin,
if
es una expresión, es decir, devuelve un valor. Por lo tanto, no existe un operador ternario(condition ? then : else)
, porque ordinario si funciona bien en este rol. fuente manual desde aquí
// 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
Algunos casos de esquina no mencionados en otras respuestas.
Desde la aparición de takeIf en Kotlin 1.1, el operador ternario a ? b : c
también puede expresarse así:
b.takeIf { a } ?: c
Esto se vuelve aún más corto en caso de que c sea null
:
b.takeIf { a }
También tenga en cuenta que las comprobaciones nulas típicas en el mundo Java, como value != null ? value : defaultValue
traducir en Kotlin ideomático a just value ?: defaultValue
.
Similar a != null ? b : c
se puede traducir a a?.let { b } ?: c
.
b.takeIf { a } ?: c
más corto y más legible que if (a) b else c
? Terneray operador es sin duda una característica que falta en Kotlin ya que los nombres de variable y la condición puede ser largo y que se divide la línea de lo que es malo
takeIf
siempre evalúa el caso verdadero (aquí a
). No solo se puede calcular esa expresión inútilmente si a
resulta ser falsa, sino que no se puede beneficiar de los lanzamientos inteligentes a la carta if (a is Int) { a + 3 }
.
{ a }
es una lambda perezosamente evaluada.
b
)". Pero incluso { a }
, aunque vago, debe evaluarse para determinar el resultado de la expresión.
Echa un vistazo a los documentos :
En Kotlin, si es una expresión, es decir, devuelve un valor. Por lo tanto, no hay operador ternario (condición? Entonces: más), porque ordinario si funciona bien en este rol.
Java
int temp = a ? b : c;
Equivalente a Kotlin:
var temp = if (a) b else c
TAREA :
Consideremos el siguiente ejemplo:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
Necesitamos el siguiente equivalente en Kotlin:
return (! answer.isSuccessful ())
?
"incorrecto":
answer.body (). string ()
SOLUCIONES :
1.a . Puedes usar if-expression
en Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.b . Puede ser mucho mejor si cambias esto if-expression
(hagámoslo sin not
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . El operador de Kotlin en Elvis ?:
puede hacer un trabajo aún mejor:
return answer.body()?.string() ?: "wrong"
3 . O use un Extension function
para la Answer
clase correspondiente :
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . Usando el Extension function
puede reducir un código gracias a Elvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . O simplemente use el when
operador:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Espero que esto ayude.
cuando reemplaza el operador de cambio de lenguajes tipo C. En la forma más simple se ve así
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when
como una declaración, no una expresión. Una comparación más relevante con las expresiones condicionales ternarias sería hacer que cada rama devuelva un valor, de modo que la expresión completa cuando se evalúe como un valor (como sucede con los condicionales ternarios).
No hay operador ternario en Kotlin. Parece problemático a primera vista. Pero piense que podemos hacerlo con la instrucción inline if else porque esta es la expresión aquí. Simplemente tenemos que hacer -
var number = if(n>0) "Positive" else "Negetive"
Aquí podemos hacerlo si bloqueamos tantos como necesitemos. Me gusta-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Entonces, esta línea es tan simple y mucho más legible que el operador ternario. Cuando utilizamos más de un operador ternario en Java, parece horrible. Pero aquí tenemos una sintaxis clara. incluso podemos escribirlo en varias líneas también.
Puede usar var a= if (a) b else c
en lugar del operador ternario.
Otro buen concepto de kotlin es el operador de Elvis. No necesita marcar nulo cada vez.
val l = b?.length ?: -1
Esto devolverá la longitud si b no es nulo; de lo contrario, se ejecuta la declaración del lado derecho.
como Drew Noakes citó, kotlin usa if enunciado como expresión, por lo que el Operador condicional ternario ya no es necesario,
pero con la función de extensión y la sobrecarga de infijo, puede implementarlo usted mismo, aquí hay un ejemplo
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
}
entonces úsalo así
val grade = 90
val clazz = (grade > 80) then "A" or "B"
Otro enfoque interesante sería usar when
:
when(a) {
true -> b
false -> b
}
Puede ser bastante útil en algunos escenarios más complejos. Y honestamente, es más legible para mí queif ... else ...
Puedes hacerlo de muchas maneras en Kotlin
Usando if
if(a) b else c
Usando cuando
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
Seguridad nula
val a = b ?: c
No hay una operación ternaria en Kotlin, pero hay algunas formas divertidas de solucionarlo. Como otros han señalado, una traducción directa a Kotlin se vería así:
val x = if (condition) result1 else result2
Pero, personalmente, creo que eso puede ser un poco abarrotado y difícil de leer. Hay algunas otras opciones integradas en la biblioteca. Puede usar takeIf {} con un operador de elvis:
val x = result1.takeIf { condition } ?: result2
Lo que sucede allí es que el comando takeIf {} devuelve su resultado1 o nulo, y el operador elvis maneja la opción nula. Hay algunas opciones adicionales, takeUnless {}, por ejemplo:
val x = result1.takeUnless { condition } ?: result2
El lenguaje es claro, ya sabes lo que está haciendo.
Si es una condición de uso común, también podría hacer algo divertido como usar un método de extensión en línea. Supongamos que queremos rastrear un puntaje de juego como Int, por ejemplo, y queremos devolver siempre 0 si no se cumple una condición determinada:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Ok, eso parece feo. Pero considere cómo se ve cuando se usa:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
Como puede ver, Kotlin ofrece mucha flexibilidad en cómo elige expresar su código. Hay innumerables variaciones de mis ejemplos y probablemente formas que aún no he descubierto. ¡Espero que esto ayude!
takeIf
Es mi opción favorita de hecho, muy elegante.
Recuerde que el operador ternario y el operador de Elvis tienen significados separados en Kotlin a diferencia de muchos idiomas populares. Hacerlo expression? value1: value2
te daría malas palabras por el compilador de Kotlin , a diferencia de cualquier otro idioma, ya que no hay un operador ternario en Kotlin como se menciona en los documentos oficiales . La razón es que las propias declaraciones if, when y try-catch devuelven valores.
Entonces, hacer expression? value1: value2
puede ser reemplazado por
val max = if (a> b) print ("Elija a") más print ("Elija b")
El operador de Elvis que tiene Kotlin , funciona solo en el caso de variables anulables, p. Ej .:
Si hago algo parecido
value3 = value1 ?: value2
a continuación, si valor1 es nula entonces valor2 se devolvería lo contrario valor1 se devolvería.
Se puede lograr una comprensión más clara de estas respuestas .
Puede usar la if
expresión para esto en Kotlin. En Kotlin if
hay una expresión con un valor de resultado. Entonces en Kotlin podemos escribir
fun max(a: Int, b: Int) = if (a > b) a else b
y en Java podemos lograr lo mismo pero con un código más grande
int max(int a, int b) {
return a > b ? a : b
}
Si no sabe qué usar la notación estándar, también puede crearla / simularla usando infijo con algo como esto:
crea una clase para mantener tu objetivo y resultado:
data class Ternary<T>(val target: T, val result: Boolean)
crear algunas funciones de infijo para simular una operación 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
}
Entonces podrás usarlo así:
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"
Otro enfoque corto para usar
val value : String = "Kotlin"
value ?: ""
Aquí kotlin comprueba el valor nulo y, si es nulo, pasa un valor de cadena vacío.
¿Por qué uno usaría algo como esto:
when(a) {
true -> b
false -> b
}
cuando realmente puedes usar algo como esto ( a
es booleano en este caso):
when {
a -> b
else -> b
}
? and :
contradice la declaración de tipo nulo / nulo en lugar de una verificación de tipo. Aparte de eso, no veo ninguna razón. Creo que alguien definitivamente habría pensado un poco, si hay una verificación en línea de la condición if-else. Esperemos y veamos en futuras versiones.
Cuando trabaje con apply (), deje que parezca muy útil cuando se trata de operaciones ternarias, ya que es más elegante y le da espacio
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 las siguientes funciones de infijo puedo cubrir muchos casos de uso comunes de la misma manera que se puede hacer en 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
No hay operador ternario en Kotlin, los más cerrados son los dos casos siguientes,
val a = true if(a) print("A is true") else print("A is false")
Si la expresión a la izquierda de?: No es nula, el operador elvis la devuelve; de lo contrario, devuelve la expresión a la derecha. Tenga en cuenta que la expresión del lado derecho se evalúa solo si el lado izquierdo es nulo.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
ejemplo: var energy: Int = data? .get (position) ?. energy? .toInt ()?: 0
En kotlin si está usando ?: Funcionará como si la declaración devuelva nulo, entonces ?: 0 tomará 0 o lo que sea que tenga escrito en este lado.
En Kotlin puedes usar operaciones ternarias como esta: val x = if(a) "add b" else "add c"
Después de investigar algunas otras ideas, he derivado el siguiente operador 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
Ejemplo (ejecutar aquí ):
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")
}
}
Esta versión es fluida y no entra en conflicto con el operador de fusión nulo.
then
lugar de yes
.