Déclaration Swift if let dans Kotlin

123

Dans Kotlin, existe-t-il un équivalent au code Swift ci-dessous?

if let a = b.val {

}
else {

}
iori24
la source

Réponses:

255

Vous pouvez utiliser la letfonction comme ceci:

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

Notez que vous devez appeler la runfonction uniquement si vous avez besoin d'un bloc de code. Vous pouvez supprimer le run-bloc si vous n'avez qu'un oneliner après l'opérateur elvis ( ?:).

Sachez que le runbloc sera évalué s'il best nul ou si le let-bloc est évalué à null.

Pour cette raison, vous ne voulez généralement qu'une ifexpression.

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

Dans ce cas, le else-bloc ne sera évalué que s'il bn'est pas nul.

Marstran
la source
42
Ce n'est pas équivalent. an'est pas accessible à l'intérieur letet dans le runbloc.
Jacky Choi
6
an'est pas encore défini dans le cadre de letet run. Mais vous pouvez accéder à la valeur de binside the letavec le paramètre implicite it. Cela sert le même objectif, je suppose.
marstran
1
Le code SWIFT termine l'attribution d' aavant ces blocs de code. Et apeut être consulté à l'intérieur.
Jacky Choi
1
À quoi attribue-t-il a? Si c'est le cas b, il itsert exactement le même objectif. Est-il réaffecté aavec le résultat du val-bloc?
marstran
3
Vous ne pouvez accéder qu'à itpartir du letbloc. Le résultat du bloc letou runsera attribué à a. Le résultat est la dernière expression du bloc. Vous utilisez l'affectation après let / runa terminé, comme vous le faites pour toute autre affectation normale.
marstran
52

Commençons par nous assurer que nous comprenons la sémantique de l'idiome Swift fourni:

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

Cela signifie ceci: "si le <expr>résultat est un optionnel non nul, entrez le thenbloc avec le symbole alié à la valeur non emballée . Sinon, entrez le elsebloc.

Notez en particulier qu'il an'est lié que dans le thenbloc- . À Kotlin, vous pouvez facilement l'obtenir en appelant

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

et vous pouvez ajouter un else-bloc comme ceci:

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

Il en résulte la même sémantique que l'idiome Swift.

Marko Topolnik
la source
11

Ma réponse est totalement une copie du chat des autres. Cependant, je ne comprends pas facilement leur expression. Je suppose donc que ce serait bien de fournir une réponse plus compréhensible.

En rapide:

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

}

À Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}
Wu Yuan Chun
la source
Utiliser letau lieu de alsosignifie que le runbloc s'exécutera à chaque letretour du bloc null, ce qui n'est pas ce que nous voulons.
Marko Topolnik
6

Contrairement à Swift, il n'est pas nécessaire de déballer l'option avant de l'utiliser dans Kotlin. Nous pourrions simplement vérifier si la valeur n'est pas nulle et le compilateur suit les informations sur la vérification que vous avez effectuée et permet de les utiliser telles quelles.

Dans Swift:

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

}

À Kotlin:

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

}

Consultez la documentation: (null-safety) pour plus de cas d'utilisation de ce type

Shahzin KS
la source
Cela ne fonctionne que si b est une variable locale. Et les variables de classe?
Warpzit
5

if let déclaration.

Swift Optional Binding(la soi-disant if-letinstruction) est utilisée pour savoir si un optionnel contient une valeur, et si c'est le cas, pour rendre cette valeur disponible comme constante ou variable temporaire. Donc, un Optional Bindingpour l' if-letinstruction est comme suit:

Déclaration de Swift if-let:

let b: Int? = 50

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

/*  RESULT: Good news!  */

Dans Kotlin, comme dans Swift, pour éviter les plantages provoqués en essayant d'accéder à une valeur nulle alors que ce n'est pas prévu, une syntaxe spécifique (comme b.let { }dans le deuxième exemple) est fournie pour un déroulement correct nullable types:

Kotlin équivalent 1 de la if-letdéclaration de Swift :

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  */

La letfonction de Kotlin , lorsqu'elle est utilisée en combinaison avec l'opérateur d'appel sécurisé ?:, fournit un moyen concis de gérer les expressions Nullable.

Kotlin équivalent 2 (fonction let en ligne et opérateur Elvis) de l' if-letinstruction de Swift :

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  */

entrez la description de l'image ici

guard let déclaration.

guard-letLa déclaration dans Swift est simple et puissante. Il vérifie certaines conditions et s'il est évalué comme faux, alors l' elseinstruction s'exécute, ce qui normalement quittera une méthode.

Explorons la guard-letdéclaration d' un Swift :

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  */

Effet similaire de Kotlin de la guard-letdéclaration de Swift :

Contrairement à Swift, à Kotlin, il n'y a aucune déclaration de garde . Cependant, vous pouvez utiliser le Elvis Operator- ?:pour obtenir un effet similaire.

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!  */

J'espère que cela t'aides.

Andy Fedoroff
la source
4

Voici comment exécuter du code uniquement lorsque namen'est pas nul:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}
Александр Яковенко
la source
si nom == code nul dans {} ne s'exécute pas, si nom sous forme de chaîne - code exécute: nomUnwrapp == nom.
Александр Яковенко
1
Je ne pense pas que ce soit ce que demande OP, je suis sûr que OP sait déjà ce que letfait, mais la question concerne la elsestratégie qui s'exécute si l'objet sur lequel letest appelé est null. Swift l'a d'une manière plus naturelle (discutable). Mais après avoir beaucoup fait à la fois Kotlin et Swift, j'aurais aimé que Kotlin ait un simple déballage comme le fait Swift.
kalehv
2

Voici ma variante, limitée au cas très courant "sinon nul".

Tout d'abord, définissez ceci quelque part:

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

Cela devrait probablement l'être internal, pour éviter les conflits.

Maintenant, convertissez ce code Swift:

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

À ce code Kotlin:

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

Notez que comme toujours avec les blocs dans Kotlin, vous pouvez supprimer l'argument et utiliser it:

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

Mais si le bloc fait plus de 1 à 2 lignes, il est probablement préférable d'être explicite.

C'est aussi similaire à Swift que je pourrais le trouver.

noamtm
la source
0

Il existe un moyen similaire dans kotlin pour obtenir le style if-let de Swift

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

Vous pouvez également attribuer plusieurs valeurs Nullable

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

Ce type d'approche sera plus approprié si les valeurs Nullable sont utilisées plus d'une fois. À mon avis, cela aide du point de vue des performances car la valeur nullable ne sera vérifiée qu'une seule fois.

source: Discussion de Kotlin

Richard
la source
1
Veuillez noter que l'approche que vous montrez ne se compile pas actuellement. Ce n'est qu'une suggestion sur la façon de modifier la langue Kotlin afin de résoudre ce problème. Par conséquent, ce n'est pas une solution valable.
Peter F
0

J'ajoute cette réponse pour clarifier la réponse acceptée car elle est trop grande pour un commentaire.

Le modèle général ici est que vous pouvez utiliser n'importe quelle combinaison des fonctions de portée disponibles dans Kotlin séparées par l' opérateur Elvis comme ceci:

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

Par exemple:

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

L'option la plus propre à mon avis est la suivante

Rapide:

if let a = b.val {

} else {

}

Kotlin

b.val.also { a ->

} ?: run {

}
Stiiv
la source
-1

Déclaration Swift if let dans Kotlin

La réponse courte est d'utiliser un simple IF-ELSE car au moment de ce commentaire, il n'y a pas d'équivalent dans Kotlin LET,

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