smart property impossible cast because kotlin

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:

  1. Use una variable local con conversión inteligente:

    val node = left if (node != null) { queue.add(node) }

  2. Use una llamada segura como una de las siguientes:

    left?.let { node -> queue.add(node) } left?.let { queue.add(it) } left?.let(queue::add)

  3. 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 and continue 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 !!