Интеллектуальное приведение к "типу" невозможно, потому что "переменная" является изменяемым свойством, которое могло быть изменено к этому времени
и новичок 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);смысл, если осталось изменил в другом потоке программа аварийно завершит работу.