Интеллектуальное приведение к "типу" невозможно, потому что "переменная" является изменяемым свойством, которое могло быть изменено к этому времени
и новичок Kotlin спрашивает: "почему следующий код не компилируется?":
var left: Node? = null
fun show() {
if (left != null) {
queue.add(left) // ERROR HERE
}
}
интеллектуальное приведение к "узлу" невозможно, потому что "левый" является изменяемым свойство, которое могло быть изменено к этому времени
я понял left
является изменяемой переменной, но я явно проверяя left != null
и left
типа Node
так почему же он не может быть умно-литым к этому типу?
как я могу исправить это элегантно? :)
2 ответа:
между исполнением
left != null
иqueue.add(left)
другой поток мог бы изменить значениеleft
доnull
.чтобы обойти это у вас есть несколько вариантов. Вот некоторые из них:
используйте локальную переменную с интеллектуальным приведением:
val node = left if (node != null) { queue.add(node) }
использовать безопасный вызов например один из следующих:
left?.let { node -> queue.add(node) } left?.let { queue.add(it) } left?.let(queue::add)
использовать оператор Элвис С
return
для раннего возврата из функции enclosing:queue.add(left ?: return)
отметим, что
break
иcontinue
может использоваться аналогично для проверок в циклах.
есть четвертый вариант в дополнение к тем, которые в ответе mfulton26.
С помощью
?.
оператор можно вызывать методы, а также поля, не имея дело сlet
или с помощью локальных переменных.код для контекста:
var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault(); socket = factory.createServerSocket(port) socket.close()//smartcast impossible socket?.close()//Smartcast possible. And works when called
он работает с методами, полями и другими вещами, которые я пытался заставить его работать.
Итак, чтобы решить эту проблему, вместо того, чтобы использовать ручные слепки или использовать локальные переменные, вы можете использовать
?.
для вызова методов.для справки, это было протестировано в Котлине
1.1.4-3
, но также проверено в1.1.51
и1.1.60
. Нет никакой гарантии, что это работает на других версиях, это может быть новая функция.С помощью
?.
оператор не может быть использован в вашем случае, так как это передается переменная в этом проблема. Оператор Elvis может быть использован в качестве альтернативы, и это, вероятно, тот, который требует наименьшего количества кода. Вместо использованияcontinue
, однако,return
также можно использовать.использование ручного литья также может быть вариантом, но это не безопасно для null:
queue.add(left as Node);
смысл, если осталось изменил в другом потоке программа аварийно завершит работу.