我正在进行Kotlin Koans测试,以便熟悉Kotlin。在某个测试中,我必须覆盖compareTo
方法。在第一种情况下,一切都按预期工作
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) {
operator fun compareTo(other: MyDate)= when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
现在在第二种情况下,我稍微改写了compareTo
,我得到了大量的编译错误。
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) {
operator fun compareTo(other: MyDate){
when {
year != other.year -> return year - other.year
month != other.month -> return month - other.month
else -> return dayOfMonth - other.dayOfMonth
}
}
}
首先,在operator关键字中,我收到错误:
'操作'修饰符不适用于此函数:必须返回Int
在我得到的回报中
类型不匹配:推断类型为Int但预期单位为
我无法理解为什么会出现这些错误,因为第一个实现会返回相同的Int
s
答案 0 :(得分:2)
在您的第一个示例中,compareTo(MyDate)
的返回类型为inferred为Int
,因为when
表达式的所有分支都返回Int
。
在第二个示例中,compareTo(MyDate)
的返回类型为Unit
。由于您的函数具有块体,因此必须明确指定返回类型(除非它们旨在让它们返回Unit
)。因此,此处需要Unit
作为返回类型,但从when
表达式推断的返回类型为Int
。这就是你得到错误的原因:
类型不匹配:推断类型为Int但预期单位为
这是official explanation,用于显式定义具有块体的函数的返回类型:
具有块体的函数必须始终明确指定返回类型,除非它们旨在让它们返回Unit in which case it is optional。 Kotlin不推断具有块体的函数的返回类型,因为这些函数可能在体内具有复杂的控制流,并且返回类型对于读者来说是不明显的(有时甚至对于编译器也是如此)。
因此,声明compareTo(MyDate)
的正确方法是指定函数的返回类型(如果它包含块体):
operator fun compareTo(other: MyDate): Int {
when {
year != other.year -> return year - other.year
month != other.month -> return month - other.month
else -> return dayOfMonth - other.dayOfMonth
}
}
这解决了另一个错误,因为comparison operator需要返回Int
。
答案 1 :(得分:1)
因为=
的作用是{ return X }
这只适用于函数定义。所以这意味着在第一个例子中你的代码等于这个
operator fun compareTo(other: MyDate):Int {
return when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
但是在你的第二个例子中,你不会返回when
的结果。这会导致编译器混淆,因为它希望您返回Int
,但返回Unit
代替(相当于Java void
)
所以你需要做的就是向它添加一个显式的返回类型(在这种情况下为Int
)(fun X(/*args*/)
: Int
或其他适用的类型)
答案 2 :(得分:0)
只是@Mibac答案的补充:你可以缩短一点:
operator fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}