Статьи

Почему все ненавидят перегрузку оператора

… нет, не говори мне, что тебе нравится Perl. Потому что ты не Вы никогда не делали. Это делает ужасные вещи. Это делает ваш код похожим на …

Perl активно использовал перегрузку операторов и использовал операторы для разных целей. Аналогичная тенденция наблюдается в  C ++  и  Scala . Смотрите также  людей, сравнивающих два . Так что не так с перегрузкой оператора?

Люди никогда не соглашались, правильно или неправильно перегружен оператор Scala:

Обычно люди ссылаются на обычных подозреваемых, таких как комплексные числа ( все получается правильно ):

class Complex(val real:Int, val imaginary:Int) {
  def +(operand:Complex):Complex = {
    new Complex(real + operand.real, imaginary + operand.imaginary)
  }

  def *(operand:Complex):Complex = {
    new Complex(real * operand.real - imaginary * operand.imaginary,
      real * operand.imaginary + imaginary * operand.real)
  }
}

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

val c1 = new Complex(1, 2)
val c2 = new Complex(2, -3)
val c3 = c1 + c2
val res = c1 + c2 * c3

Но есть  такие странные знаки препинания,  которые просто сводят с ума обычных программистов:

 ->
 ||=
 ++=
 <=
 _._
 ::
 :+=

Не верь этому? Проверьте эту библиотеку графов !

На вышесказанное мы говорим:

Перегрузка оператора? Мех

Как должна  быть перегрузка оператора 

Перегрузка оператора  может  быть хорошей, но в  основном  это не так. В Java все мы упускаем лучшие способы взаимодействия с  BigDecimal  и аналогичными типами:

// How it is:
bigdecimal1.add(bigdecimal2.multiply(bigdecimal3));
// How it should be:
bigdecimal1 + bigdecimal2 * bigdecimal3

Конечно, приоритет оператора будет иметь место, как и ожидалось. В отличие от C ++ или Scala, идеальная перегрузка операторов просто отображает общие операторы на общие имена методов. Больше ничего. Никто не хочет, чтобы разработчики API придумали модных  ##-%>> операторов.

В то время как  CeylonGroovy и  Xtend  реализовали это несколько предсказуемым и полезным способом,  Kotlin  , вероятно, является языком, который реализовал лучший стандартный механизм перегрузки операторов в их язык. Их документация гласит:

Бинарные операции

ЭКСПРЕССИЯ Переведено на
а + б a.plus (б)
а — б a.minus (б)
а * б a.times (б)
а / б a.div (б)
% b a.mod (б)
a..b a.rangeTo (б)

Это выглядит довольно просто. Теперь проверьте это:

«Массив» доступ

СИМВОЛ Переведено на
а [я] a.get (я)
a [i, j] a.get (i, j)
a [i_1, …, i_n] a.get (i_1,…, i_n)
a [i] = b a.set (i, b)
a [i, j] = b a.set (i, j, b)
a [i_1, …, i_n] = b a.set (i_1,…, i_n, b)

Теперь я действительно не вижу ни одного аргумента против вышесказанного. Это продолжается, и, к сожалению, Java 8 пропустила эту последовательность, так как  ссылки на методы не могут быть назначены переменным и вызваны как функции JavaScript (хотя это не слишком поздно для Java 9+):

Вызовы метода

СИМВОЛ Переведено на
а (я) a.invoke (я)
a (i, j) a.invoke (i, j)
a (i_1,…, i_n) a.invoke (i_1,…, i_n)

Просто красиво!

Вывод

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

Будем надеяться, что будущие версии Java будут вдохновлены Kotlin, языком, который правильно перегрузил операторов.