Jaki jest odpowiednik tego wyrażenia w Kotlinie?
a ? b : c
To nie jest poprawny kod w Kotlin.
Jaki jest odpowiednik tego wyrażenia w Kotlinie?
a ? b : c
To nie jest poprawny kod w Kotlin.
Odpowiedzi:
W Kotlinie if
wyrażenia są wyrażeniami. Zatem następujący kod jest równoważny:
if (a) b else c
Ważne jest tutaj rozróżnienie między wyrażeniem a stwierdzeniem. W Javie / C # / JavaScript if
tworzy instrukcję, co oznacza, że nie jest rozpoznawana jako wartość. Mówiąc konkretniej, nie można przypisać jej do zmiennej.
// Valid Kotlin, but invalid Java/C#/JavaScript
var v = if (a) b else c
Jeśli pochodzisz z języka, w którym if
znajduje się wypowiedź, może się to wydawać nienaturalne, ale to uczucie wkrótce powinno ustąpić.
when
.
x = a==b
b + if (a) c else d
vs. b + (c if (a) else d)
Ten ostatni wymaga dodatkowych nawiasów. ponieważ c
nie jest objęty warunkiem i else
.
Możesz zdefiniować własną Boolean
funkcję rozszerzenia, która zwraca się, null
gdy Boolean
ma false
zapewnić strukturę podobną do operatora trójskładnikowego:
infix fun <T> Boolean.then(param: T): T? = if (this) param else null
To by a ? b : c
tłumaczyło wyrażenie a then b ?: c
tak:
println(condition then "yes" ?: "no")
Aktualizacja: Ale aby zrobić więcej przełączników warunkowych podobnych do Javy, potrzebujesz czegoś takiego
infix fun <T> Boolean.then(param: () -> T): T? = if (this) param() else null
println(condition then { "yes" } ?: "no")
zwracaj uwagę na lambda. jego obliczanie zawartość powinna zostać odroczone do czasu upewnić condition
siętrue
Ten wygląda na niezgrabny, dlatego istnieje duże zapotrzebowanie na przeniesienie trójskładnikowego operatora Java do Kotlin
infix inline fun<T> Boolean.then(param: ()->T):T? = if(this) param() else null
true then { null } ?: "not-null"
?:
tutaj operator to elvis-operator
: kotlinlang.org/docs/reference/null-safety.html#elvis-operator
if (a) b else c
to, czego możesz użyć zamiast wyrażenia operatora trójskładnikowego a ? b : c
.
W Kotlin wiele wyrażeń kontrolnych, w tym if
, when
a nawet try
może być używanych jako wyrażenia . Oznacza to, że mogą one mieć wynik, który można przypisać do zmiennej, zwrócony z funkcji itp.
W wyniku wyrażeń Kotlina język tak naprawdę nie potrzebuje operatora potrójnego .
if (a) b else c
to, czego możesz użyć zamiast wyrażenia operatora trójskładnikowego a ? b : c
.
Myślę, że chodzi o to, że poprzednie wyrażenie jest bardziej czytelne, ponieważ wszyscy wiedzą, co ifelse
robi, a ? :
raczej niejasne, jeśli nie znasz już składni.
Niemniej jednak muszę przyznać, że często brakuje mi wygodniejszego operatora trójskładnikowego.
Inne alternatywy
kiedy
Podczas when
sprawdzania warunków możesz także zobaczyć konstrukcje używane w Kotlinie. Jest to również sposób na wyrażenie alternatywnych kaskad. Poniższy przykład odpowiada OT.
when(a) {
true -> b
false -> c
}
Rozszerzenia
Jak pokazuje wiele dobrych przykładów ( Kotlin Ternary Conditional Operator ) w innych odpowiedziach, rozszerzenia mogą również pomóc w rozwiązaniu twojego przypadku użycia.
Dla siebie korzystam z następujących funkcji rozszerzających:
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
Pierwszy zwróci podaną wartość domyślną, jeśli obiekt jest równy null. Drugi oceni wyrażenie podane w lambda w tym samym przypadku.
Stosowanie:
1) e?.getMessage().or("unknown")
2) obj?.lastMessage?.timestamp.or { Date() }
Osobiście dla mnie kod powyżej bardziej czytelny niż if
wstawianie konstrukcji
e.getMessage() ?: "unknown"
. Drugi można wyrazić jakoobj?.lastMessage?.timestamp ?: { Date() }()
Jawny odpowiednik operatora trójskładnikowego
a ? b : c
to prosty IF w Kotlinie w jednej linii
if(a) b else c
nie ma operatora trójskładnikowego (warunek? to: else), ponieważ zwykły jeśli działa dobrze w tej roli.
https://kotlinlang.org/docs/reference/control-flow.html#if-expression
Specjalny przypadek dla porównania Null
możesz skorzystać z operatora Elvisa
if ( a != null ) a else b
// equivalent to
a ?: b
W kotlin nie ma operatora trójskładnikowego , ponieważ if else
blok zwraca wartość
więc możesz zrobić:
val max = if (a > b) a else b
zamiast javamax = (a > b) ? b : c
Możemy również użyć when
konstrukcji, to także zwraca wartość:
val max = when(a > b) {
true -> a
false -> b
}
Oto link do dokumentacji kotlin: Control Flow: if, when, for, while
W Kotlinie
if
jest wyrażeniem, tzn. Zwraca wartość. Dlatego nie ma operatora trójskładnikowego(condition ? then : else)
, ponieważ zwykły jeśli działa dobrze w tej roli. źródło ręczne stąd
// 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
Niektóre przypadki narożne niewymienione w innych odpowiedziach.
Od momentu pojawienia się takeIf w Kotlin 1.1 operator trójskładnikowy a ? b : c
można również wyrazić w następujący sposób:
b.takeIf { a } ?: c
Staje się to jeszcze krótsze, gdy c wynosi null
:
b.takeIf { a }
Zauważ też, że typowe w świecie Java kontrole zerowe, takie jak value != null ? value : defaultValue
przetłumaczenie ideomatycznego Kotlina na just value ?: defaultValue
.
Podobne a != null ? b : c
można przetłumaczyć na a?.let { b } ?: c
.
b.takeIf { a } ?: c
krótszy i bardziej czytelny niż if (a) b else c
? Operator Terneray jest z pewnością brakującą cechą w Kotlin, ponieważ nazwy zmiennych i warunek mogą być długie i powodować, że dzielisz linię, która jest zła
takeIf
zawsze ocenia prawdziwy przypadek (tutaj a
). To wyrażenie może być nie tylko bezużyteczne, jeśli okaże a
się fałszywe, ale nie możesz skorzystać z inteligentnych rzutów à la if (a is Int) { a + 3 }
.
{ a }
to leniwie oceniana lambda.
b
)”. Ale nawet { a }
leniwy musi zostać oceniony, aby określić wynik wyrażenia.
Jawa
int temp = a ? b : c;
Odpowiednik Kotlin :
var temp = if (a) b else c
ZADANIE :
Rozważmy następujący przykład:
if (!answer.isSuccessful()) {
result = "wrong"
} else {
result = answer.body().string()
}
return result
Potrzebujemy następującego odpowiednika w Kotlin:
return (! answer.isSuccessful ())
?
„zły”:
answer.body (). string ()
ROZWIĄZANIA :
1.a . Możesz użyć if-expression
w Kotlin:
return if (!answer.isSuccessful()) "wrong" else answer.body().string()
1.b . Może być znacznie lepiej, jeśli odwrócisz to if-expression
(zróbmy to bez not
):
return if (answer.isSuccessful()) answer.body().string() else "wrong"
2 . Operator Elvisa z Kotlin ?:
może wykonać pracę jeszcze lepiej:
return answer.body()?.string() ?: "wrong"
3 . Lub użyj Extension function
dla odpowiedniej Answer
klasy:
fun Answer.bodyOrNull(): Body? = if (isSuccessful()) body() else null
4 . Za pomocą Extension function
możesz zmniejszyć kod dzięki Elvis operator
:
return answer.bodyOrNull()?.string() ?: "wrong"
5 . Lub po prostu użyj when
operatora:
when (!answer.isSuccessful()) {
parseInt(str) -> result = "wrong"
else -> result = answer.body().string()
}
Mam nadzieję że to pomoże.
po zastąpieniu operatora przełączania języków podobnych do C. W najprostszej formie wygląda to tak
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when
wyrażenie, a nie wyrażenie. Bardziej odpowiednie porównanie z trójskładnikowymi wyrażeniami warunkowymi polega na tym, aby każda gałąź zwróciła wartość, tak że całe wyrażenie po wyrażeniu zwraca wartość (jak ma to miejsce w przypadku trójkowych wyrażeń warunkowych).
W Kotlinie nie ma operatora trójskładnikowego. Na pierwszy rzut oka wydaje się to problematyczne. Ale pomyśl, że możemy to zrobić za pomocą instrukcji inline if else, ponieważ jest to wyrażenie tutaj. Po prostu musimy zrobić -
var number = if(n>0) "Positive" else "Negetive"
Tutaj możemy jeszcze zablokować zbyt wiele, ile potrzebujemy. Lubić-
var number = if(n>0) "Positive" else if(n<0) "Negative" else "Zero"
Ta linia jest więc tak prosta i czytelna jak operator trójskładnikowy. kiedy używamy więcej niż jednego trójskładnikowego operatora w Javie, wydaje się to okropne. Ale tutaj mamy jasną składnię. nawet my możemy napisać to w wielu wierszach.
Możesz użyć var a= if (a) b else c
zamiast operatora trójskładnikowego.
Kolejną dobrą koncepcją kotlina jest Elvis. Nie musisz za każdym razem sprawdzać wartości null.
val l = b?.length ?: -1
Zwróci długość, jeśli b nie ma wartości null, w przeciwnym razie wykona instrukcję po prawej stronie.
jak cytował Drew Noakes, kotlin używa instrukcji if jako wyrażenia, więc Ternary Operator warunkowy nie jest już potrzebny,
ale z funkcją rozszerzenia i przeciążeniem infix możesz sam to zaimplementować, oto przykład
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
}
następnie użyj tego w ten sposób
val grade = 90
val clazz = (grade > 80) then "A" or "B"
Innym ciekawym podejściem byłoby użycie when
:
when(a) {
true -> b
false -> b
}
Może być bardzo przydatny w niektórych bardziej złożonych scenariuszach. I szczerze mówiąc, jest to dla mnie bardziej czytelne niżif ... else ...
Możesz to zrobić na wiele sposobów w Kotlinie
Używanie if
if(a) b else c
Używanie kiedy
when (a) {
true -> print("value b")
false -> print("value c")
else -> {
print("default return in any other case")
}
}
Brak bezpieczeństwa
val a = b ?: c
W Kotlinie nie ma operacji trójskładnikowych, ale istnieją fajne sposoby obejścia tego. Jak zauważyli inni, bezpośrednie tłumaczenie na Kotlin wyglądałoby tak:
val x = if (condition) result1 else result2
Ale osobiście uważam, że może to być trochę zagracone i trudne do odczytania. Istnieje kilka innych opcji wbudowanych w bibliotekę. Możesz użyć takeIf {} z operatorem elvis:
val x = result1.takeIf { condition } ?: result2
To, co się dzieje, polega na tym, że komenda takeIf {} zwraca albo wynik1 albo null, a operator elvis obsługuje opcję null. Istnieją dodatkowe opcje, takeUnless {}, na przykład:
val x = result1.takeUnless { condition } ?: result2
Język jest jasny, wiesz, co się dzieje.
Jeśli jest to często używany warunek, możesz także zrobić coś fajnego, na przykład użyć wbudowanej metody rozszerzenia. Załóżmy, że chcemy na przykład śledzić wynik gry jako Int i chcemy zawsze zwracać 0, jeśli dany warunek nie jest spełniony:
inline fun Int.zeroIfFalse(func: () -> Boolean) : Int = if (!func.invoke()) 0 else this
Ok, to wydaje się brzydkie. Zastanów się jednak, jak to wygląda, gdy jest używane:
var score = 0
val twoPointer = 2
val threePointer = 3
score += twoPointer.zeroIfFalse { scoreCondition }
score += threePointer.zeroIfFalse { scoreCondition }
Jak widać, Kotlin oferuje dużą elastyczność w sposobie wyrażania kodu. Istnieją niezliczone warianty moich przykładów i prawdopodobnie sposoby, których jeszcze nie odkryłem. Mam nadzieję, że to pomoże!
takeIf
to rzeczywiście moja ulubiona opcja, bardzo elegancka.
Pamiętaj, że operator trójskładnikowy i operator Elvisa mają odrębne znaczenia w Kotlin, w przeciwieństwie do wielu popularnych języków. Spowodowałoby expression? value1: value2
to złe słowa kompilatora Kotlin , w przeciwieństwie do innych języków, ponieważ w Kotlinie nie ma potrójnego operatora, jak wspomniano w oficjalnych dokumentach . Powodem jest to, że same instrukcje if, kiedy i try-catch zwracają wartości.
Tak więc robienie expression? value1: value2
można zastąpić
val max = if (a> b) print („Choose a”) else print („Choose b”)
Operator Elvis że Kotlin ma, działa tylko w przypadku wartości pustych zmiennych np .:
Jeśli zrobić coś jak
value3 = value1 ?: value2
wtedy, gdy wartosc1 jest zerowa następnie value2 zostaną zwrócone w przeciwnym razie wartosc1 będą zwracane.
Dzięki tym odpowiedziom można lepiej zrozumieć .
Możesz użyć if
do tego wyrażenia w Kotlinie. W Kotlinie if
jest wyrażenie z wartością wynikową. W Kotlinie możemy pisać
fun max(a: Int, b: Int) = if (a > b) a else b
a w Javie możemy osiągnąć to samo, ale z większym kodem
int max(int a, int b) {
return a > b ? a : b
}
Jeśli nie używasz standardowej notacji, możesz ją również utworzyć / symulować za pomocą infix z czymś takim:
utwórz klasę, aby utrzymać swój cel i wynik:
data class Ternary<T>(val target: T, val result: Boolean)
utwórz niektóre funkcje poprawki, aby zasymulować operację potrójną
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
}
Następnie będziesz mógł użyć go w następujący sposób:
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"
Kolejne krótkie podejście do użycia
val value : String = "Kotlin"
value ?: ""
Tutaj sam kotlin sprawdza wartość zerową, a jeśli jest zerowy, to przekazuje pustą wartość ciągu.
Dlaczego miałby używać czegoś takiego:
when(a) {
true -> b
false -> b
}
kiedy możesz użyć czegoś takiego ( a
w tym przypadku jest to boolean):
when {
a -> b
else -> b
}
? and :
sprzeczne z deklaracją zerowania / typu, a nie z kontrolą typu. Poza tym nie widzę żadnego powodu. Myślę, że ktoś na pewno by się nad tym zastanowił, jeśli istnieje wbudowana kontrola warunku „jeśli-inaczej”. Poczekajmy i zobaczymy w przyszłych wersjach.
Podczas pracy z funkcją apply () wydaje się bardzo przydatna w przypadku operacji trójkowych, ponieważ jest bardziej elegancka i daje ci miejsce
val columns: List<String> = ...
val band = Band().apply {
name = columns[0]
album = columns[1]
year = columns[2].takeIf { it.isNotEmpty() }?.let { it.toInt() } ?: 0
}
Dzięki następującym funkcjom poprawki mogę objąć wiele typowych przypadków użycia w taki sam sposób, jak w Pythonie:
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
W Kotlinie nie ma operatora trójskładnikowego, najbardziej zamknięte są poniższe dwa przypadki,
val a = true if(a) print("A is true") else print("A is false")
Jeśli wyrażenie po lewej stronie?: Nie jest puste, operator elvis zwraca je, w przeciwnym razie zwraca wyrażenie po prawej. Zauważ, że wyrażenie po prawej stronie jest oceniane tylko wtedy, gdy lewa strona jest pusta.
val name = node.getName() ?: throw IllegalArgumentException("name expected")
przykład: var energy: Int = data? .get (position) ?. energy? .toInt ()?: 0
W kotlin, jeśli używasz ?: To będzie działało tak, jakby instrukcja zwróciła null, to ?: 0 zajmie 0 lub cokolwiek, co masz napisać po tej stronie.
W Kotlin możesz użyć operacji trójskładnikowej w następujący sposób: val x = if(a) "add b" else "add c"
Po kilku badaniach innych pomysłów, wyprowadziłem następujący operator trójskładnikowy:
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
Przykład (uruchom tutaj ):
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")
}
}
Ta wersja jest płynna i nie koliduje z zerowym operatorem koalescencji.
then
zamiast yes
.