Smart Cast a 'Tipo' es imposible, porque 'variable' es una propiedad mutable que podría haber cambiado en este momento

Y el novato de Kotlin pregunta: "¿por qué no se comstackrá el siguiente código?" :

var left: Node? = null fun show() { if (left != null) { queue.add(left) // ERROR HERE } } 

El lanzamiento inteligente a 'Nodo' es imposible, porque 'izquierda' es una propiedad mutable que podría haberse cambiado en este momento

Veo que la variable mutable left es, pero estoy comprobando explícitamente left != null y left es de tipo Node entonces ¿por qué no puede ser smart-casted para ese tipo?

¿Cómo puedo arreglar esto elegantemente? 🙂

Entre la ejecución de n.left != null queue.add(n.left) y queue.add(n.left) otro hilo podría haber cambiado el valor de n.left a null .

Para solucionar esto, tiene varias opciones. Aquí están algunas:

  1. Usa una variable local con smart cast:

     val left = n.left if (left != null) { queue.add(left) } 
  2. Use una llamada segura como una de las siguientes:

     n.left?.let { left -> queue.add(left) } n.left?.let { queue.add(it) } n.left?.let(queue::add) 
  3. Utilice el operador de Elvis con un salto al siguiente paso del bucle while encierra:

     queue.add(n.left ?: continue) 

Hay una cuarta opción además de las que están en la respuesta de mfulton26.

Al usar el ?. Es posible llamar tanto a los methods como a los campos sin tener que lidiar con let o usar variables locales.

Algunos códigos para el context:

 var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault(); socket = factory.createServerSocket(port) socket.close()//smartcast impossible socket?.close()//Smartcast possible. And works when called 

Funciona con methods, campos y todas las otras cosas que intenté para que funcione.

Entonces, para resolver el problema, en lugar de tener que usar moldes manuales o usar variables locales, puede usar ?. para llamar a los methods.

Como reference, 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 característica nueva.

Usando el ?. El operador no puede usarse en su caso, ya que es una variable pasada el problema. El operador de Elvis se puede utilizar como alternativa, y es probablemente el que requiere la menor cantidad de código. Sin embargo, en lugar de continue , el return también podría ser utilizado.

Usar el lanzamiento manual también podría ser una opción, pero esto no es seguro.

 queue.add(left as Node); 

Es decir, si la izquierda ha cambiado en un hilo diferente, el progtwig se bloqueará.

  • Fragmento en kotlin
  • Kotlin Android Library Module exportado con gradle maven-publish plugin sin agregar dependencies
  • GMaps Android API y GeoJson, cómo cubrir todo el mundo con un agujero
  • ¿Kotlin tiene un tipo de "rasgo"?
  • ¿Cuál es el uso previsto de @JvmSynthetic en Kotlin?
  • Anotaciones de Kotlin en properties delegadas
  • Retrofit se bloquea cuando lanzo una exception en un interceptor
  • Error con java8 y Kotlin
  • Spring Boot ThymeLeaf y Kotlin: ¿el valor de la casilla no se pasa al controller?
  • Advertencia: la opción '-d' con un destino de directory se ignora porque se especifica '-module'
  • ¿Cómo puedo inicializar la variable antes de cada testing usando el marco kotlin-test