Kotlin新手问:“为什么下面的代码不能编译?”:

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

智能转换为'Node'是不可能的,因为'left'是可变的 此时可以更改的属性

我得到left is mutable变量,但我显式检查left != null left是Node类型,为什么它不能被智能转换为这种类型?

我该如何优雅地解决这个问题?


当前回答

这样做:

var left: Node? = null

fun show() {
     val left = left
     if (left != null) {
         queue.add(left) // safe cast succeeds
     }
}

这似乎是公认答案提供的第一个选项,但这正是您要寻找的。

其他回答

Change var left: Node?= null to lateinit var left:节点。问题解决了。

我会怎么写:

var left: Node? = null

fun show() {
     val left = left ?: return
     queue.add(left) // no error because we return if it is null
}

你最优雅的解决方案必须是:

var left: Node? = null

fun show() {
    left?.also {
        queue.add( it )
    }
}

这样就不需要定义一个新的、不必要的局部变量,也不需要任何新的断言或强制类型转换(它们都不是DRY)。其他作用域函数也可以工作,所以选择您最喜欢的。

这样做:

var left: Node? = null

fun show() {
     val left = left
     if (left != null) {
         queue.add(left) // safe cast succeeds
     }
}

这似乎是公认答案提供的第一个选项,但这正是您要寻找的。

要使属性具有Smart Cast,属性的数据类型必须是包含您想要访问的方法或行为的类,而不是属性为超类的类型。


例如在Android上

Be:

class MyVM : ViewModel() {
    fun onClick() {}
}

解决方案:

From: private lateinit var viewModel: ViewModel
To: private lateinit var viewModel: MyVM

用法:

viewModel = ViewModelProvider(this)[MyVM::class.java]
viewModel.onClick {}

GL