E o novato em Kotlin pergunta: "Por que o código a seguir não é compilado?":
var left: Node? = null
fun show() {
if (left != null) {
queue.add(left) // ERROR HERE
}
}
A conversão inteligente para 'Nó' é impossível, porque 'esquerda' é uma propriedade mutável que poderia ter sido alterada nesse momento
Recebo que left
é uma variável mutável, mas estou verificando explicitamente left != null
e left
é do tipo, Node
por que não pode ser transmitida de forma inteligente para esse tipo?
Como posso corrigir isso de forma elegante? :)
n.left?.let { queue.add(it) }
eu acho?Respostas:
Entre execução de
left != null
equeue.add(left)
outro encadeamento poderia ter alterado o valor deleft
paranull
.Para contornar isso, você tem várias opções. Aqui estão alguns:
Use uma variável local com conversão inteligente:
Use uma chamada segura , como uma das seguintes opções:
Use o operador Elvis com
return
para retornar cedo da função de fechamento:Observe que
break
econtinue
pode ser usado de forma semelhante para verificações dentro de loops.fonte
Node
classe definida na versão original da pergunta que tinha um trecho de código mais complicado, emn.left
vez de simplesmenteleft
. Atualizei a resposta de acordo. Obrigado.val
para cada umvar
, aninhar várias?.let
instruções ou usar várias?: return
instruções, dependendo da sua função. por exemploMyAsyncTask().execute(a1 ?: return, a2 ?: return, a3 ?: return)
. Você também pode tentar uma das soluções para uma "variável múltipla" .1) Também é possível usar
lateinit
Se você com certeza inicializar mais tardeonCreate()
ou em outro lugar.Usa isto
Em vez disso
2) E existe outra maneira de usar o
!!
fim da variável quando você a usa assimfonte
Existe uma quarta opção além das da resposta de mfulton26.
Ao usar o
?.
operador, é possível chamar métodos e campos sem lidar comlet
ou usar variáveis locais.Algum código para o contexto:
Funciona com métodos, campos e todas as outras coisas que tentei fazer funcionar.
Portanto, para resolver o problema, em vez de precisar usar projeções manuais ou variáveis locais, você pode usar
?.
para chamar os métodos.Para referência, isso foi testado em Kotlin
1.1.4-3
, mas também testado em1.1.51
e1.1.60
. Não há garantia de que funcione em outras versões; pode ser um novo recurso.O uso do
?.
operador não pode ser usado no seu caso, já que é uma variável transmitida que é o problema. O operador Elvis pode ser usado como uma alternativa e provavelmente é o que requer a menor quantidade de código. Em vez de usarcontinue
, porém,return
também pode ser usado.O uso da transmissão manual também pode ser uma opção, mas isso não é seguro para nulos:
Ou seja, se a esquerda foi alterada em um segmento diferente, o programa falhará.
fonte
left
e nãoqueue
. Necessidade de verificar isso, vai editar a resposta em um minutoA razão prática pela qual isso não funciona não está relacionada a threads. O ponto é que
node.left
é efetivamente traduzido paranode.getLeft()
.Este getter de propriedade pode ser definido como:
Portanto, duas chamadas podem não retornar o mesmo resultado.
fonte
Mude
var left: Node? = null
paralateinit var left: Node
. Problema resolvido.fonte
Faça isso:
Qual parece ser a primeira opção fornecida pela resposta aceita, mas é isso que você está procurando.
fonte
Para que haja uma conversão inteligente das propriedades, o tipo de dados da propriedade deve ser a classe que contém o método ou o comportamento que você deseja acessar e NÃO que a propriedade seja do tipo da superclasse.
por exemplo, no Android
Estar:
Solução:
Uso:
GL
fonte
Sua solução mais elegante deve ser:
Então você não precisa definir uma variável local nova e desnecessária e não possui nenhuma nova asserção ou conversão (que não seja SECA). Outras funções de escopo também podem funcionar, então escolha o seu favorito.
fonte
Tente usar o operador de asserção não nulo ...
fonte
Como eu escreveria:
fonte