В Kotlin поддерживается перегрузка операторов (operator overloading) через ключевое слово operator. Это позволяет определять собственную логику работы стандартных операторов (+, -, *, [], ==, и др.) для пользовательских типов:
operator.Пример:
data class Vec2(val x: Int, val y: Int) { operator fun plus(other: Vec2) = Vec2(x + other.x, y + other.y) } val a = Vec2(1,2) val b = Vec2(2,3) val c = a + b // вызовет operator fun plus
Нюансы и best practice:
== и equals должны быть согласованы).Чем отличается перегрузка оператора
==от переопределения методаequals()?
Ответ: Оператор == в Kotlin всегда вызывает метод equals() (с предварительной проверкой на null). Если вы определяете operator fun equals(other: Any?): Boolean, оператором == будет всегда пользоваться именно этот метод. Нельзя сделать так, чтобы == и equals() работали по-разному.
data class Point(val x: Int, val y: Int) { override operator fun equals(other: Any?): Boolean { ... } } val a = Point(1,2) val b = Point(1,2) println(a == b) // вызовет a.equals(b)
История
Перегрузили оператор compareTo без явной семантики:
В классе Point определили operator fun compareTo для возможности использовать в сортировках. Однако "больше" и "меньше" не имели явного смысла, разные члены команды писали различную логику. Результат — запутанные баги при сортировке коллекций.
История
Забыли про симметричность операторов для обоюдных типов:
Разработчик реализовал operator fun plus(a: Matrix, b: Vector): Matrix, но не обеспечил работу для Vector + Matrix, т.к. не реализовал симметричную функцию.
В результате выражение vector + matrix не компилировалось, только matrix + vector работало. Это вызвало баги во многих частях кода.
История
Ошибочная перегрузка оператора get:
Разработчик сделал custom-класс, перегрузив operator fun get(index: Int): Foo. Не добавил проверки выхода за пределы — и попытка доступа к несуществующему элементу возвращала объект с невалидными полями, а не бросала исключение — что привело к появлению "невидимых" ошибок в бизнес-логике.