在14th Kotlin Koan on运算符重载时,我很惊讶,在解决后我查看了答案并发现operator
修饰符 <{1}}方法:
compareTo
与练习相关联的operator overloading docs明确表示:
需要使用运算符标记重载运算符的函数 改性剂。
那么这里发生了什么?为什么这段代码会编译?何时需要data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
?
答案 0 :(得分:8)
为什么这段代码会编译?
这是编译,因为重写的界面方法Comparable<T>.compareTo
, 是operator fun
。
/**
* Compares this object with the specified object for order. Returns zero if this object is equal
* to the specified [other] object, a negative number if it's less than [other], or a positive number
* if it's greater than [other].
*/
public operator fun compareTo(other: T): Int
当函数覆盖它时,它也是一个操作符函数。
一般情况下,只要你希望能够使用函数就像运算符一样,何时需要
operator
?
operator
是必需的,因为运算符用法只是编译为函数调用(基本类型等除外)
也就是说,foo += bar
相当于foo.plusAssign(bar)
,foo[bar] = baz
相当于foo.set(bar, baz)
等。
出于可读性原因,我个人更喜欢尽可能指定operator
,即使不是必需的。
如果MyDate
不 Comparable
,您省略了operator
修饰符,则通过<
,{{1}比较两个日期},>
或<=
无法编译。
虽然我在specification找不到任何内容。然而,在多态意义上它是有道理的 - 为什么你应该能够写>=
a < b
和a
的类型为b
,而不是当它们是Comparable
时MyDate
?由于您无法删除此函数的“operator-ness”,因此operator
应该可以从超类方法继承。
答案 1 :(得分:4)
Kotlin具有许多通过特定约定启用的功能。可以使用operator
关键字来识别这些内容。示例包括范围,运算符重载, 索引运算符,解构声明等。
如果我们想比较Java中的两个对象,例如,我们使用Comparable
方法实现compareTo
接口。这也是在Kotlin中完成的,但有更好的支持和简写语法。如果在类中实现此方法,则可以使用开箱即用的所有类似<
,<=
,>
,>=
等优秀运算符。这些运算符被编译器转换为compareTo
的适当调用:
obj1 > obj2
⇒obj1.compareTo(obj2) > 0
The interface method compareTo
in Comparable
已经定义了operator
关键字,这使得在您自己的实现中添加关键字变得多余。
在您的示例中,operator
关键字不是必需的,因为重写的方法已经定义了它。