android - 为什么 Kotlin 编译器在有效的 IF 语句中给出错误?
问题描述
它开始在Kotlin中出现一个非常奇怪的编译器错误
所以我把我的代码简化为最简单的形式。代码没有意义,但尝试理解错误的来源要容易得多。
我已经在Kotlin Playground中发布了我的代码。所以我不依赖于我的计算机的任何本地配置,并且任何人都可以在任何地方立即重现错误。
我的完整代码
data class Pilha(
var funs: ArrayList<Int>
= arrayListOf<Int>()
)
var AP: Array<Pilha> = Array<Pilha>(5) { Pilha() }
fun main() {
var ele: String=""
var cl: String = ""
when (ele) {
"soul" -> {
with(AP[0]) {
when {
(cl == "%") -> {
if (funs[0]==1) // <= error in this line
cl = "a"
}
cl == "xU" -> {
// If I comment this line, the error disappears
funs.add(2)
}
else -> { cl="b" } // else of inner when
} // when
} // with
} // "soul"
else->{ cl="c"} // else of outer when
} // when
println("ok")
} // main
错误信息
if must have both main and 'else' branches if used as an expression
此错误在此行中给出
if (funs[0]==1)
如果我评论这一行,错误就会消失
funs.add(2)
这是一个很大的谜,因为很明显这是一个有效的if
流量控制语句。我没有if
用作表达。
显然在这上面加上一个死else
(else {}
)if
也可以解决错误,但不要解释它。
科特林游乐场:
更新:正如 Pawel向我指出的那样,这是一个类型返回冲突的问题,与with
语句相关联。因为我是一个经典的Pascal 程序员,所以我在使用with
Pascal 用户是如何做到的。
为此,最好像 Pawel 所说,使用object.apply {}
. 因此,在 的情况下with
,可以直接使用对象的属性和方法,而无需括号 ({}) 内的访问器点。
解决方案
您正在使用with(AP[0]) { ... }
带有 lambda 签名的函数T.() -> R
。它需要 lambda 中的返回值,并且其中的最后一条语句是when
块,因此它用作确定返回值的表达式。
错误是因为在这种情况下cl == %
并且funs[0]!=1
无法确定要返回的值。
with
通过用不需要返回值的范围函数替换你来修复它,例如AP[0].apply { ... }
签名为T.() -> Unit
.
编辑:为什么注释掉funs.add(2)
“修复”错误?
这是因为该调用返回的Boolean
值会改变整个when
块的签名:
// this when block can be used as an expression because it returns value of type Any
when {
(cl == "%") -> if (funs[0]==1) cl = "a" // if true returns Unit, else undefined
cl == "xU" -> { funs.add(2) } // returns Boolean
else -> cl="b" // does not return value (Unit)
}
现在,当您注释掉funs.add(2)
或将第二种情况更改为{funs.add(2) ; Unit }
this 时,整个when
块的返回类型为 a Unit
,这意味着它不再用作表达式并且不需要返回值。
// this when block cannot be used as an expression because it always returns Unit (void)
when {
(cl == "%") -> if (funs[0]==1) cl = "a" // does not return value (Unit)
cl == "xU" -> { funs.add(2); Unit } // ignore add return value by returning Unit
else -> cl="b" // does not return value (Unit)
}
推荐阅读
- javascript - 动画比例反应
- php - 如何在 Wordpress 中创建社交证明插件
- javascript - 在未附加到 DOM 的函数中创建的元素
- android - 如何解决库中的此错误?
- ionic-framework - 在 Ionic 上实施 Azure AD B2C
- angular - Express API 调用 Angular 6 没有数据
- python - Matplotlib 图只在循环中制作最终图
- c# - ASP.Net 中继器绑定但无法正确呈现
- vba - 根据当前记录的值与前一个相比更改标签的颜色
- cakephp - CircleCI & Cakephp - 无法连接到数据库进行 phpunit 测试