Swift if let Aussage in Kotlin

122

Gibt es in Kotlin ein Äquivalent zum Swift-Code unten?

if let a = b.val {

}
else {

}
iori24
quelle

Antworten:

255

Sie können die let-funktion folgendermaßen verwenden:

val a = b?.let {
    // If b is not null.
} ?: run {
    // If b is null.
}

Beachten Sie, dass Sie die runFunktion nur aufrufen müssen, wenn Sie einen Codeblock benötigen. Sie können den run-block entfernen, wenn Sie nur nach dem elvis-operator ( ?:) einen Oneliner haben .

Beachten Sie, dass der runBlock entweder ausgewertet wird, wenn er bnull ist, oder wenn der let-block ausgewertet wird null.

Aus diesem Grund möchten Sie normalerweise nur einen ifAusdruck.

val a = if (b == null) {
    // ...
} else {
    // ...
}

In diesem Fall wird der else-block nur ausgewertet, wenn er bnicht null ist.

Marstran
quelle
40
Es ist nicht gleichwertig. akann nicht innerhalb letund runBlock zugegriffen werden .
Jacky Choi
6
aist noch nicht im Rahmen von letund definiert run. Sie können jedoch mit dem impliziten Parameter auf den Wert von binside zugreifen . Dies dient dem gleichen Zweck, den ich denke. letit
Marstran
1
Der schnelle Code vervollständigt die Zuweisung avor diesen Codeblöcken. Und akann innen zugegriffen werden.
Jacky Choi
1
Wem wird es zugewiesen a? Wenn ja b, dann itdient genau der gleiche Zweck. Wird es amit dem Ergebnis des valBlocks neu zugewiesen ?
Marstran
3
Sie können nur itinnerhalb des letBlocks zugreifen . Das Ergebnis des Blocks letoder runwird zugewiesen a. Das Ergebnis ist der letzte Ausdruck im Block. Sie verwenden die Aufgabe nach let / runbeendet, genau wie bei jeder anderen normalen Aufgabe.
Marstran
51

Stellen wir zunächst sicher, dass wir die Semantik der bereitgestellten Swift-Sprache verstehen:

if let a = <expr> {
     // then-block
}
else {
     // else-block
}

Dies bedeutet Folgendes: "Wenn die <expr>Ergebnisse nicht optional sind, geben Sie den thenBlock mit dem Symbol ein a, das an den nicht umschlossenen Wert gebunden ist. Andernfalls geben Sie den elseBlock ein.

Beachten Sie insbesondere, dass nur innerhalb des -blocksa gebunden ist . In Kotlin können Sie dies ganz einfach telefonisch erreichenthen

<expr>?.also { a ->
    // then-block
}

und Sie können einen elseBlock wie folgt hinzufügen :

<expr>?.also { a ->
    // then-block
} ?: run {
    // else-block
}

Dies führt zu derselben Semantik wie das Swift-Idiom.

Marko Topolnik
quelle
11

Meine Antwort ist total eine Nachahmerkatze von den anderen. Ich kann ihren Ausdruck jedoch nicht leicht verstehen. Ich denke, es wäre schön, eine verständlichere Antwort zu geben.

In Kürze:

if let a = b.val {
  //use "a" as unwrapped
}
else {

}

In Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}
Wu Yuan Chun
quelle
Verwenden von letanstelle von alsobedeutet, dass der runBlock immer dann ausgeführt wird, wenn der letBlock zurückkehrt null, was nicht das ist, was wir wollen.
Marko Topolnik
5

Im Gegensatz zu Swift ist es nicht erforderlich, das Optionale zu entpacken, bevor Sie es in Kotlin verwenden. Wir könnten einfach prüfen, ob der Wert nicht null ist, und der Compiler verfolgt die Informationen über die von Ihnen durchgeführte Prüfung und erlaubt, sie als entpackt zu verwenden.

In Swift:

if let a = b.val {
  //use "a" as unwrapped
} else {

}

In Kotlin:

if b.val != null {
  //use "b.val" as unwrapped
} else {

}

Weitere derartige Anwendungsfälle finden Sie in der Dokumentation: (Null-Sicherheit)

Shahzin KS
quelle
Dies funktioniert nur, wenn b eine lokale Variable ist. Was ist mit Klassenvariablen?
Warpzit
5

if let Aussage.

Swift's Optional Binding(sogenannte if-letAnweisung) wird verwendet, um herauszufinden, ob ein optionales Element einen Wert enthält, und wenn ja, um diesen Wert als temporäre Konstante oder Variable verfügbar zu machen. Ein Optional Bindingfür die if-letAussage lautet also wie folgt:

Swifts if-letAussage:

let b: Int? = 50

if let a = b {
    print("Good news!")
} else {
    print("Equal to 'nil' or not set")
}

/*  RESULT: Good news!  */

In Kotlin wird wie in Swift eine bestimmte Syntax (wie b.let { }im zweiten Beispiel) bereitgestellt , um Abstürze zu vermeiden, die durch den Versuch verursacht werden, auf einen Nullwert zuzugreifen, wenn dies nicht erwartet wird nullable types:

Kotlin-Äquivalent 1 von Swifts if-letAussage:

val b: Int? = null
val a = b

if (a != null) { 
    println("Good news!")
} else { 
    println("Equal to 'null' or not set")
}

/*  RESULT: Equal to 'null' or not set  */

Die Kotlin- letFunktion bietet in Kombination mit dem Safe-Call-Operator ?:eine übersichtliche Möglichkeit, nullbare Ausdrücke zu verarbeiten.

Kotlin-Äquivalent 2 (Inline-Let-Funktion und Elvis-Operator) von Swifts if-letAussage:

val b: Int? = null

val a = b.let { nonNullable -> nonNullable } ?: "Equal to 'null' or not set"
println(a)

/*  RESULT: Equal to 'null' or not set  */

Geben Sie hier die Bildbeschreibung ein

guard let Aussage.

guard-letAussage in Swift ist einfach und mächtig. Es prüft auf eine Bedingung und wenn es als falsch ausgewertet wird, wird die elseAnweisung ausgeführt, die normalerweise eine Methode beendet.

Lassen Sie uns die guard-letAussage eines Swift untersuchen :

let b: Int? = nil

func testIt() {
    guard let a = b else {
        print("Equal to 'nil' or not set")
        return
    }
    print("Good news!")
}
testIt()

/*  RESULT: Equal to 'nil' or not set  */

Kotlins ähnlicher Effekt von Swifts guard-letAussage:

Im Gegensatz zu Swift gibt es in Kotlin überhaupt keine Wachaussage . Sie können jedoch das Elvis Operator- verwenden ?:, um einen ähnlichen Effekt zu erzielen.

val b: Int? = 50

fun testIt() {
    val a = b ?: return println("Equal to 'null' or not set")
    return println("Good news!")
}
testIt()

/*  RESULT: Good news!  */

Hoffe das hilft.

Andy Fedoroff
quelle
4

So führen Sie Code nur aus, wenn er namenicht null ist:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}
Александр Яковенко
quelle
Wenn name == null Code in {} nicht ausgeführt wird, wenn name als String - Code ausgeführt wird: nameUnwrapp == name.
Александр Яковенко
1
Ich glaube nicht, dass OP dies verlangt, ich bin sicher, dass OP bereits weiß, was es lettut, aber die Frage betrifft die elseStrategie, die ausgeführt wird, wenn das Objekt, auf dem letaufgerufen wird, ist null. Swift hat es auf natürlichere (fragwürdige) Weise. Aber nachdem ich sowohl Kotlin als auch Swift viel getan habe, wünschte ich mir, Kotlin hätte ein einfaches Auspacken wie Swift.
Kalehv
2

Hier ist meine Variante, die auf den sehr häufigen Fall "wenn nicht null" beschränkt ist.

Definieren Sie dies zunächst irgendwo:

inline fun <T> ifNotNull(obj: T?, block: (T) -> Unit) {
    if (obj != null) {
        block(obj)
    }
}

Es sollte wahrscheinlich sein internal, um Konflikte zu vermeiden.

Konvertieren Sie nun diesen Swift-Code:

if let item = obj.item {
    doSomething(item)
}

Zu diesem Kotlin-Code:

ifNotNull(obj.item) { item -> 
    doSomething(item)
}

Beachten Sie, dass Sie wie immer bei Blöcken in Kotlin das Argument löschen und Folgendes verwenden können it:

ifNotNull(obj.item) {
    doSomething(it)
}

Wenn der Block jedoch mehr als 1-2 Zeilen umfasst, ist es wahrscheinlich am besten, explizit zu sein.

Dies ist Swift so ähnlich, wie ich es finden konnte.

noamtm
quelle
0

In Kotlin gibt es einen ähnlichen Weg, um Swifts Stil zu erreichen

if (val a = b) {
    a.doFirst()
    a.doSecond()
}

Sie können auch mehrere nullbare Werte zuweisen

if (val name = nullableName, val age = nullableAge) {
    doSomething(name, age)
}

Diese Art von Ansatz ist besser geeignet, wenn die nullbaren Werte mehr als einmal verwendet werden. Meiner Meinung nach hilft dies unter Leistungsaspekten, da der nullbare Wert nur einmal überprüft wird.

Quelle: Kotlin Diskussion

Richard
quelle
1
Bitte beachten Sie, dass der angezeigte Ansatz derzeit nicht kompiliert wird. Es ist nur ein Vorschlag, wie die Kotlin-Sprache geändert werden kann, um dieses Problem zu lösen. Daher ist dies keine gültige Lösung.
Peter F
0

Ich füge diese Antwort hinzu, um die akzeptierte Antwort zu verdeutlichen, da sie für einen Kommentar zu groß ist.

Das allgemeine Muster ist , dass Sie eine beliebige Kombination der Verwendung können Scope Funktionen in Kotlin von dem abgetrennten Elvis Operator wie folgt aus :

<nullable>?.<scope function> {
    // code if not null
} :? <scope function> {
    // code if null
}

Beispielsweise:

val gradedStudent = student?.apply {
    grade = newGrade
} :? with(newGrade) {
    Student().apply { grade = newGrade }
}
Sir Codesalot
quelle
-1

Die sauberste Option ist meiner Meinung nach dies

Schnell:

if let a = b.val {

} else {

}

Kotlin

b.val.also { a ->

} ?: run {

}
Stiiv
quelle
-1

Swift if let Aussage in Kotlin

Die kurze Antwort lautet: Verwenden Sie einfach IF-ELSE, da es zum Zeitpunkt dieses Kommentars kein Äquivalent in Kotlin LET gibt.

    if(A.isNull()){
// A is null
    }else{
// A is not null
    }
bastami82
quelle