kotlin - property - La conversión inteligente a ''Tipo'' es imposible, porque ''variable'' es una propiedad mutable que podría haberse cambiado en este momento
smart cast is impossible because mutable property (6)
Entre la ejecución de
left != null
queue.add(left)
y
queue.add(left)
otro subproceso podría haber cambiado el valor de
left
a
null
.
Para solucionar esto, tiene varias opciones. Aquí están algunas:
-
Use una variable local con conversión inteligente:
val node = left if (node != null) { queue.add(node) }
-
Use una llamada segura como una de las siguientes:
left?.let { node -> queue.add(node) } left?.let { queue.add(it) } left?.let(queue::add)
-
Utilice el operador de Elvis con
return
para regresar antes de la función de cierre:queue.add(left ?: return)
Tenga en cuenta que
break
andcontinue
se puede usar de manera similar para las comprobaciones dentro de los bucles.
Y el novato de Kotlin pregunta: "¿por qué no se compilará el siguiente código?":
var left: Node? = null
fun show() {
if (left != null) {
queue.add(left) // ERROR HERE
}
}
La conversión inteligente a ''Nodo'' es imposible, porque ''izquierda'' es una propiedad mutable que podría haberse cambiado en este momento
Entiendo que la
left
es una variable mutable, pero estoy comprobando explícitamente
left != null
y
left
es de tipo
Node
¿por qué no se puede convertir de forma inteligente en ese tipo?
¿Cómo puedo arreglar esto con elegancia? :)
Hacer esto:
var left: Node? = null
fun show() {
val left = left
if (left != null) {
queue.add(left) // safe cast succeeds
}
}
Que parece ser la primera opción proporcionada por la respuesta aceptada, pero eso es lo que estás buscando.
Hay una cuarta opción además de las de la respuesta de mfulton26.
Al usar el
?.
operador es posible llamar a métodos y campos sin tener que lidiar con
let
o usar variables locales.
Algún código para el contexto:
var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault();
socket = factory.createServerSocket(port)
socket.close()//smartcast impossible
socket?.close()//Smartcast possible. And works when called
Funciona con métodos, campos y todas las demás cosas que intenté para que funcione.
Entonces, para resolver el problema, en lugar de tener que usar conversiones manuales o usar variables locales, puede usar
?.
para llamar a los métodos.
Como referencia, esto se probó en Kotlin
1.1.4-3
, pero también se probó en
1.1.51
y
1.1.60
.
No hay garantía de que funcione en otras versiones, podría ser una nueva característica.
Usando el
?.
El operador no se puede utilizar en su caso, ya que el problema es una variable pasada.
El operador de Elvis se puede usar como alternativa, y probablemente sea el que requiera la menor cantidad de código.
Sin embargo, en lugar de usar
continue
,
return
también podría usarse.
El uso de la conversión manual también podría ser una opción, pero esto no es nulo seguro:
queue.add(left as Node);
Es decir, si la izquierda ha cambiado en un hilo diferente, el programa se bloqueará.
Intente usar el operador de aserción no nulo ...
queue.add(left!!)
La razón práctica por la que esto no funciona no está relacionada con los hilos.
El punto es que
node.left
se traduce efectivamente en
node.getLeft()
.
Este captador de propiedades se puede definir como:
val left get() = if (Math.random() < 0.5) null else leftPtr
Por lo tanto, dos llamadas podrían no devolver el mismo resultado.
También puede usar
lateinit
si realiza su inicialización más adelante en
onCreate()
o en otro lugar.
Utilizar esta
lateinit var left: Node
En lugar de esto
var left: Node? = null
¡Y hay otra forma de usarlo
!!
fin de variable cuando lo usas así
queue.add(left!!) // add !!