Kotlin中所需的运算符关键字是什么时候?

在第14次操作符重载的Kotlin Koan中 ,我惊讶地发现解决方案后,我看到了答案,并且看到compareTo方法不需要operator修饰符:

 data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable { override fun compareTo(other: MyDate) = when { year != other.year -> year - other.year month != other.month -> month - other.month else -> dayOfMonth - other.dayOfMonth } } 

运营商重载的文档中明确指出:

超载操作符需要用运算符修饰符标记。

那么这里发生了什么? 为什么这个代码编译? 何时需要operator

为什么这个代码编译?

这个编译是因为重写的接口方法Comparable.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

一般来说,只要你希望能够像使用操作符一样使用函数,就需要操作符,因为操作符的用法只是编译成函数调用(除了基本types等)

也就是说, foo += bar等同于foo.plusAssign(bar)foo[bar] = baz相当于foo.set(bar, baz)等。

就我个人而言,为了可读性的原因,我希望尽可能地指定operator即使不是必需的。

如果MyDate 不是 Comparable ,并且省略了operator修饰符,则通过<><=>=比较两个日期将不会被编译。

虽然在规范中我找不到任何东西。 然而,从多态的角度来说,这是有道理的 - 为什么你应该能够写a < b ,其中ab的types是Comparable ,而不是当它们是MyDate ? 既然你不能删除这个函数的“运算符”,那么operator应该是可以从超类方法inheritance的。

Kotlin具有许多通过特定惯例启用的function。 这些可以通过使用operator关键字来识别。 范例是范围操作符重载, 索引操作符解构声明等等。

如果我们想在Java中比较两个对象,例如,我们使用它的compareTo方法来实现Comparable接口。 这也是在Kotlin中完成的,但具有更好的支持和简短的语法。 如果你在一个类中实现了这个方法,那么你可以使用<<=>>=等所有不错的运算符。 这些运算符被编译器翻译为适当的compareTo调用:

obj1 > obj2 obj1.compareTo(obj2) > 0

compareTo中的接口方法compareTo已经定义了operator关键字,这使得在您自己的实现中添加关键字成为多余的。

在你的例子中, operator关键字不是强制的,因为重写的方法已经定义了它。