什么时候Kotlin需要运营商关键字?

Tom*_*sky 18 operator-overloading kotlin

14日科特林公案操作符重载,我很惊讶,当解决后,我看到了答案,看到的operator是修改要求对compareTo方法:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

操作符重载文档链接到从锻炼明确地说:

需要使用运算符修饰符标记重载运算符的函数.

那么这里发生了什么?为什么这段代码会编译?什么时候operator需要?

Moi*_*ira 12

为什么这段代码会编译?

这将编译因为重写的界面的方法,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
Run Code Online (Sandbox Code Playgroud)

由于函数覆盖了它,它也是一个操作符函数.

什么时候operator需要?

operator 一般来说,只要你希望能够使用一个函数,就像它是一个操作符一样,这​​是必需的,因为操作符用法只是被编译成函数调用(基本类型等除外)

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

就个人而言operator,出于可读性原因,我更愿意尽可能指定,即使不需要.

如果MyDate没有一个Comparable,而你省略了operator修改,通过比较两个日期<,>,<=>=不会进行编译.

不过,我在规范中找不到任何东西.然而,在一个多态的意义上,它是有道理的-为什么你应该能够编写a < b的,其中类型abComparableS,而不是当他们是MyDate?由于您无法删除此函数的"operator-ness",因此operator应该可以从超类方法继承.

  • >只要你希望能够使用一个函数就好像它是一个运算符<正确,但不仅如此:`getValue` /`setValue` /`provideDelegate`运算符没有运算符形式.我宁愿说它是具有可以调用的另一种约定的函数的关键字. (2认同)

s1m*_*nw1 5

Kotlin具有许多通过特定约定启用的功能。这些可以通过使用operator关键字来识别。示例包括range运算符重载, 索引运算符解构声明等。

如果要比较Java中的两个对象,以进行排序,则可以Comparable使用其compareTo方法来实现接口。这在Kotlin中也可以完成,但是具有更好的支持和简化的语法。如果你在一个类中实现此方法,您可以使用所有漂亮的运营商如<<=>>=与该类开箱。compareTo编译器将这些运算符转换为适当的调用:

obj1 > obj2obj1.compareTo(obj2) > 0

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

在您的示例中,operator关键字不是必需的,因为覆盖方法已经定义了它。


Sof*_*uni 5

在 Java 中,运算符与特定的 Java 类型相关联。例如,Java 中的 String 和 numeric 类型可以分别使用 + 运算符进行连接和加法。没有其他 Java 类型可以为了自己的利益重用这个运算符。相反,Kotlin 提供了一组约定来支持有限的运算符重载。

让我们从一个简单的数据类开始:

data class Point(val x: Int, val y: Int)
Run Code Online (Sandbox Code Playgroud)

我们将使用一些运算符来增强这个数据类。

为了将具有预定义名称的 Kotlin 函数转换为运算符,我们应该使用运算符修饰符标记该函数。例如,我们可以重载“+”运算符:

operator fun Point.plus(other: Point) = Point(x + other.x, y + other.y)
Run Code Online (Sandbox Code Playgroud)

这样我们就可以用“+”添加两个点:

val p1 = 点(0, 1)

val p2 = 点(1, 2)

打印(p1 + p2)

点(x=1,y=3)