Когда именно ключевое слово оператора требуется в Котлине?

В 14-м Kotlin Koan при перегрузке оператора я был удивлен, когда после решения я просмотрел ответ и увидел, что модификатор 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 } } 

Оператор перегружает документы, связанные с упражнением, явно говорит:

Функции, которые перегружают операторы, должны быть отмечены модификатором оператора.

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

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

    Это компилируется, потому что метод переопределенного интерфейса, Comparable<T>.compareTo , является operator fun для 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 , сравнение двух дат с помощью < , > , <= или >= не будет компилироваться.

    Тем не менее, я не мог найти ничего в спецификации . Однако в полиморфном смысле это имеет смысл – почему вы должны писать a < b где тип a и b являются Comparable s, но не когда они являются MyDate ? Поскольку вы не сможете удалить «оператор» этой функции, имеет смысл, что operator должен наследоваться от метода суперкласса.

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

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

    obj1 > obj2obj1.compareTo(obj2) > 0

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

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

    Interesting Posts

    RealmMigrationNeededException при добавлении RealmList <Int> (Kotlin)

    Недействительный Mutable Map

    Сортировка списка по заказу другого списка

    kotlin лямбда-выражения в качестве необязательного параметра

    Kotlin: как параметр по умолчанию в «fun main (parameters: Array <String>)» печатает «гость» без присвоения каких-либо значений

    Использование стандартных элементов HTML в KotlinJS безопасно напечатано

    Параметр, заданный как ненулевой, имеет значение NULL при использовании Mokito anyObject () для функции Kotlin

    Spring & kotlin: В чем разница между инсталляцией конструктора и латинита?

    Общие понятия Котлина: несоответствие типов в параметре общей карты

    NPE в квадратичном оптимизаторе ojAlgo

    Цепочные обещания с пользовательскими типами ошибок с Kovenant

    Fade excludeTarget не работает внутри DrawerLayout

    Как передать аргументы компилятора компилятору Kotlin с Gradle

    Как заставить вызовы некоторым конструкторам / функциям использовать именованные аргументы?

    Котлин. Ожидается Любой полученный MyObject

    Давайте будем гением компьютера.