Swift if let declaração em Kotlin

123

Em Kotlin, existe um equivalente ao código Swift abaixo?

if let a = b.val {

}
else {

}
iori24
fonte

Respostas:

255

Você pode usar a letfunção-assim:

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

Observe que você precisa chamar a runfunção apenas se precisar de um bloco de código. Você pode remover o run-block se tiver apenas um oneliner após o operador-elvis ( ?:).

Esteja ciente de que o runbloco será avaliado se bfor nulo ou se o let-block for avaliado como null.

Por causa disso, você geralmente quer apenas uma ifexpressão.

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

Nesse caso, o else-block só será avaliado se bnão for nulo.

marstran
fonte
41
Não é equivalente. anão pode ser acessado dentro lete runbloco.
Jacky Choi de
6
aainda não está definido dentro do escopo de lete run. Mas você pode acessar o valor de bdentro de letcom o parâmetro implícito it. Isso tem o mesmo propósito, eu acho.
marstran de
1
O código swift completa a atribuição de aantes desses blocos de código. E apode ser acessado por dentro.
Jacky Choi
1
A que atribui a? Se for b, então ittem exatamente o mesmo propósito. Ele reatribui acom o resultado do val-block?
marstran de
3
Você só pode acessar itde dentro do letbloco. O resultado do bloco letou runserá atribuído a a. O resultado é a última expressão do bloco. Você usa a tarefa após let / runterminar, como faria com qualquer outra tarefa normal.
marstran
51

Vamos primeiro garantir que entendemos a semântica do idioma Swift fornecido:

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

Significa o seguinte: "se o <expr>resultado for um opcional não nulo, insira o then-bloco com o símbolo avinculado ao valor não empacotado. Caso contrário, insira o elsebloco.

Observe especialmente que aestá vinculado apenas ao thenbloco -block . Em Kotlin, você pode fazer isso facilmente chamando

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

e você pode adicionar um else-bloco como este:

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

Isso resulta na mesma semântica do idioma Swift.

Marko Topolnik
fonte
11

Minha resposta é totalmente uma cópia dos outros. No entanto, não consigo entender sua expressão facilmente. Acho que seria bom fornecer uma resposta mais compreensível.

Rapidamente:

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

}

Em Kotlin:

b.val?.let{a -> 
  //use "a" as unwrapped
} ?: run{
  //else case
}
Wu Yuan Chun
fonte
Usar em letvez de alsosignifica que o runbloco será executado sempre que o letbloco retornar null, o que não é o que queremos.
Marko Topolnik
6

Ao contrário do Swift, não é necessário desembrulhar o opcional antes de usá-lo no Kotlin. Poderíamos apenas verificar se o valor não é nulo e o compilador rastreia as informações sobre a verificação que você executou e permite usá-la como desembrulhada.

Em Swift:

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

}

Em Kotlin:

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

}

Consulte a Documentação: (segurança nula) para mais casos de uso

Shahzin KS
fonte
Isso só funciona se b for uma variável local. E quanto às variáveis ​​de classe?
Warpzit
5

if let declaração.

O Swift's Optional Binding(a chamada if-letinstrução) é usado para descobrir se um opcional contém um valor e, em caso afirmativo, para disponibilizar esse valor como uma constante ou variável temporária. Portanto, um Optional Bindingpara a if-letdeclaração é o seguinte:

if-letDeclaração de Swift :

let b: Int? = 50

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

/*  RESULT: Good news!  */

No Kotlin, como no Swift, para evitar travamentos causados ​​ao tentar acessar um valor nulo quando não é esperado, uma sintaxe específica (como b.let { }no segundo exemplo) é fornecida para desempacotar corretamente nullable types:

Kotlin equivalente 1 da if-letdeclaração 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  */

A letfunção de Kotlin , quando usada em combinação com o operador de chamada segura ?:, fornece uma maneira concisa de lidar com expressões anuláveis.

Kotlin equivalente 2 (função Inline let e Operador Elvis) da if-letdeclaração 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  */

insira a descrição da imagem aqui

guard let declaração.

guard-letdeclaração em Swift é simples e poderosa. Ele verifica se há alguma condição e, se for avaliada como falsa, a elseinstrução é executada, normalmente encerrando um método.

Vamos explorar a guard-letdeclaração de 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  */

Efeito semelhante de Kotlin na guard-letdeclaração de Swift :

Ao contrário de Swift, em Kotlin, não há nenhuma instrução de guarda . No entanto, você pode usar Elvis Operator- ?:para obter um efeito semelhante.

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

Espero que isto ajude.

Andy Fedoroff
fonte
4

Veja como executar código apenas quando namenão for nulo:

var name: String? = null
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // not printed because name was null
}
name = "Alex"
name?.let { nameUnwrapp ->
    println(nameUnwrapp)  // printed "Alex"
}
Александр Яковенко
fonte
se nome == código nulo em {} não execute, se nome como String - código execute: nomeUnwrapp == nome.
Александр Яковенко
1
Não acho que seja isso que OP está perguntando, tenho certeza de que OP já sabe o que letfaz, mas a questão é sobre a elseestratégia que executa se o objeto no qual leté chamado o for null. Swift tem isso de forma mais natural (discutível). Mas, tendo feito muito Kotlin e Swift, gostaria que Kotlin tivesse um desembrulhamento simples como o Swift faz.
kalehv
2

Aqui está minha variante, limitada ao caso muito comum "se não nulo".

Em primeiro lugar, defina isso em algum lugar:

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

Provavelmente deveria ser internal, para evitar conflitos.

Agora, converta este código Swift:

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

Para este código Kotlin:

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

Observe que, como sempre acontece com blocos em Kotlin, você pode descartar o argumento e usar it:

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

Mas se o bloco tiver mais de 1-2 linhas, provavelmente é melhor ser explícito.

É o mais semelhante ao Swift que pude encontrar.

noamtm
fonte
0

Existe uma maneira semelhante no kotlin para alcançar o estilo do Swift se-let

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

Você também pode atribuir vários valores anuláveis

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

Esse tipo de abordagem será mais adequado se os valores anuláveis ​​forem usados ​​por mais de 1 vez. Na minha opinião, ajuda do aspecto de desempenho porque o valor anulável será verificado apenas uma vez.

fonte: Discussão de Kotlin

Richard
fonte
1
Esteja ciente de que a abordagem que você está mostrando não compila atualmente. É apenas uma sugestão de como alterar a linguagem Kotlin para lidar com esse problema. Portanto, esta não é uma solução válida.
Peter F
0

Estou adicionando esta resposta para esclarecer a resposta aceita porque é muito grande para um comentário.

O padrão geral aqui é que você pode usar qualquer combinação das Funções de Escopo disponíveis no Kotlin separadas pelo Operador Elvis assim:

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

Por exemplo:

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

A opção mais limpa na minha opinião é esta

Rápido:

if let a = b.val {

} else {

}

Kotlin

b.val.also { a ->

} ?: run {

}
Stiiv
fonte
-1

Swift if let declaração em Kotlin

A resposta curta é usar IF-ELSE simples , pois no momento deste comentário não há equivalente no Kotlin LET,

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