Когда именно ключевое слово оператора требуется в 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
    }
}

на перегрузка оператора docs связанный с упражнением явно говорит:

функции которым операторам перегрузки нужно быть маркированным с оператором модификатор.

так что происходит здесь? Почему этот код компилируется? Когда именно operator требуются?

2 ответов


почему этот код компилируется?

это компилируется, потому что переопределенный метод интерфейса,Comparable<T>.compareTo, и an 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), etc.

лично я предпочитаю задание operator везде, где это возможно, даже если это не требуется, для удобства чтения причинам.

если MyDate были не a Comparable, а вы опустили operator модификатор, сравнивая две даты через <, >, <= или >= не будет компилироваться.

я не смог найти ничего в спецификация несмотря на это,. Однако в полиморфном смысле это имеет смысл-почему вы должны уметь писать a < b где типа a и b are Comparables, но не тогда, когда они MyDate? Поскольку вы не сможете удалить "оператор-Несс" этой функции, это имеет смысл, что operator должен быть наследуемым от метода суперкласса.


Kotlin имеет множество функций, которые включены через particular конвенций. Они могут быть идентифицированы с помощью operator ключевое слово. Примеры диапазоны, перегрузки операторов, операторы индекса, деструктурируется заявления и многое другое.

если мы хотим сравнить два объекта в Java, для сортировки, например, мы реализуем Comparable интерфейс с compareTo метод. Это также делается в Kotlin, но с гораздо лучшей поддержкой и синтаксисом стенографии. Если вы реализуете этот метод в классе, вы можете использовать все хорошие операторы, такие как <, <=, >, >= С этим классом из коробки. Эти операторы переводятся на соответствующие вызовы compareTo компилятором:

obj1 > obj2obj1.compareTo(obj2) > 0

метод интерфейса compareTo на Comparable уже определяет operator ключевое слово, что делает его избыточным, чтобы добавить ключевое слово в свой собственный реализация.

в вашем примере operator ключевое слово не является обязательным, так как переопределенный метод уже определяет его.