Respostas:
Você pode usar a let
função-assim:
val a = b?.let {
// If b is not null.
} ?: run {
// If b is null.
}
Observe que você precisa chamar a run
funçã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 run
bloco será avaliado se b
for nulo ou se o let
-block for avaliado como null
.
Por causa disso, você geralmente quer apenas uma if
expressão.
val a = if (b == null) {
// ...
} else {
// ...
}
Nesse caso, o else
-block só será avaliado se b
não for nulo.
a
ainda não está definido dentro do escopo de let
e run
. Mas você pode acessar o valor de b
dentro de let
com o parâmetro implícito it
. Isso tem o mesmo propósito, eu acho.
a
antes desses blocos de código. E a
pode ser acessado por dentro.
a
? Se for b
, então it
tem exatamente o mesmo propósito. Ele reatribui a
com o resultado do val
-block?
it
de dentro do let
bloco. O resultado do bloco let
ou run
será atribuído a a
. O resultado é a última expressão do bloco. Você usa a tarefa após let
/ run
terminar, como faria com qualquer outra tarefa normal.
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 a
vinculado ao valor não empacotado. Caso contrário, insira o else
bloco.
Observe especialmente que a
está vinculado apenas ao then
bloco -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.
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
}
let
vez de also
significa que o run
bloco será executado sempre que o let
bloco retornar null
, o que não é o que queremos.
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
if let
declaração.O Swift's Optional Binding
(a chamada if-let
instruçã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 Binding
para a if-let
declaração é o seguinte:
if-let
Declaraçã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-let
declaraçã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 let
funçã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-let
declaraçã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 */
guard let
declaração.guard-let
declaração em Swift é simples e poderosa. Ele verifica se há alguma condição e, se for avaliada como falsa, a else
instrução é executada, normalmente encerrando um método.
Vamos explorar a
guard-let
declaraçã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-let
declaraçã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.
Veja como executar código apenas quando name
nã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"
}
let
faz, mas a questão é sobre a else
estraté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.
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.
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
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 }
}
a
não pode ser acessado dentrolet
erun
bloco.