Почему Java не нуждается в перегрузке операторов? [закрыто]

17
задан Rob Hruska 24 August 2010 в 18:15
поделиться

8 ответов

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

14
ответ дан 30 November 2019 в 11:07
поделиться

Дело не в том, что java не «нуждается» в перегрузке операторов, это просто выбор, сделанный ее создателями, которые хотели сделать язык более простым.

2
ответ дан 30 November 2019 в 11:07
поделиться

Java не поддерживает перегрузку операторов (одна ссылка - это страница Википедии о перегрузке операторов ). Это было дизайнерское решение создателей Java, чтобы избежать предполагаемых проблем, возникающих при перегрузке операторов в других языках (особенно C ++).

0
ответ дан 30 November 2019 в 11:07
поделиться

Этот связанный вопрос может помочь. Короче говоря, при разработке Java намеренно избегали перегрузки операторов из-за проблем с перегрузкой в ​​C++.

Scala, более новый язык JVM, имеет синтаксис, который позволяет перегружать метод, который очень похож на перегрузку операторов, но без ограничений перегрузки операторов C++. Например, в Scala можно определить метод с именем +. Также можно опустить . оператор и круглые скобки в вызовах методов:

case class A(value: Int) {
   def +(other: A) = new A(value + other.value)
}

scala> new A(1) + new A(3)                                                           
res0: A = A(4)
7
ответ дан 30 November 2019 в 11:07
поделиться

Java не нуждается в перегрузке операторов, потому что язык не нуждается.

a + b — это просто «синтаксический сахар» для a.Add(b) (на самом деле некоторые утверждают, что a.Add(b) — это просто синтаксический сахар для Добавить(a,b))

8
ответ дан 30 November 2019 в 11:07
поделиться

Java не поддерживает перегрузку операторов программистами. Это не то же самое, что утверждать, что Java не нуждается в перегрузке операторов.

Перегрузка оператора — это синтаксический сахар для выражения операции с использованием (арифметических) символов. По понятным причинам разработчики языка программирования Java отказались от поддержки перегрузки операторов в языке. Это объявление можно найти в белой книге Java Language Environment:

Нет средств, с помощью которых программисты могут перегрузить стандартный арифметические операторы. Еще раз, последствия перегрузки оператора могут быть так же легко достигается путем объявления класс, соответствующие переменные экземпляра, и соответствующие методы манипулирования эти переменные. Исключающий оператор перегрузка приводит к большим упрощение кода.

По моему личному мнению, это мудрое решение.Рассмотрим следующий фрагмент кода:

String b = "b";
String c = "c";
String a = b + c;

Теперь совершенно очевидно, что b и c объединяются, чтобы получить a. Но если рассмотреть следующий фрагмент кода, написанный с использованием гипотетического языка, поддерживающего перегрузку операторов, становится очевидным, что использование перегрузки операторов не делает код читабельным.

Person b = new Person("B");
Person c = new Person("C");
Person a = b + c;

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

Person b = new Person("B");
Person c = new Person("C");
Person a = b.copyAttributesFrom(c);
2
ответ дан 30 November 2019 в 11:07
поделиться

Ни один язык не требует перегрузки оператора. Некоторые считают, что Java выиграет от его добавления, но его упущение так долго рекламировалось как преимущество, что его добавление почти наверняка политически неприемлемо (и только после выкупа Oracle я бы даже включил «почти»).

Контрапункт обычно состоит из постулирования некоторой бессмысленной (или даже нелогичной) перегрузки, такой как сложение двух сотрудников или перегрузка «+» для деления. В то время как перегрузка операторов в таких языках, как C++, позволила бы это сделать, отсутствие перегрузки операторов в Java мало что делает для предотвращения или даже смягчения проблемы. someEmployee.Add(anotherEmployee) ничем не лучше, чем someEmployee + AnotherEmployee. Аналогично, если myLargeInteger.Add(anotherLargeInteger) действительно выполняет деление вместо сложения. По крайней мере, мне эта аргументация кажется в лучшем случае совершенно неубедительной.

Однако есть и другой аспект, в котором отказ от перегрузки операторов (почти наверняка) приносит реальную пользу. Его отсутствие упрощает обработку языка, что значительно упрощает (и ускоряет) разработку инструментов, обрабатывающих язык. Просто для наглядного примера: инструменты рефакторинга для Java гораздо более многочисленны и универсальны, чем для C++.Я сомневаюсь, что это может или должно быть приписано конкретно и исключительно поддержке перегрузки операторов в C++ и ее упущению в Java. Тем не менее, общее отношение к простоте Java (включая отказ от перегрузки операторов), несомненно, является важным фактором.

Была поднята возможность упростить синтаксический анализ, требуя пробелов между идентификаторами и операторами (например, a+b запрещено, но a + b разрешено). По крайней мере, на мой взгляд, в большинстве случаев это вряд ли имеет какое-то реальное значение. Причина довольно проста: по крайней мере, в типичном компиляторе синтаксическому анализатору предшествует лексер. Лексер извлекает токены из входного потока и передает их синтаксическому анализатору. При такой структуре синтаксический анализатор вообще не увидит разницы между a+b и a+b. В любом случае он получит ровно три токена: идентификатор, + и идентификатор.

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

Итак, если проблема не в этом, то в чем? Проблема с перегрузкой операторов заключается в том, что вы не можете жестко запрограммировать синтаксический анализатор, чтобы он знал значение оператора.В Java для некоторого заданного a = b + c есть ровно две возможности: a, b и c выбираются из небольшого ограниченного набора типов, и смысл этого + запечен в языке, иначе у вас ошибка. Таким образом, инструмент, который должен смотреть на b + c и понимать их, может выполнить очень минимальный анализ, чтобы гарантировать, что b и c относятся к типам, которые можно добавлять. Если да, то он знает, что означает сложение, какой результат оно дает и так далее. Если это не так, он может подчеркнуть это красными волнистыми линиями (или что-то еще), чтобы указать на ошибку.

Для C++ все обстоит иначе. Для выражения типа a = b + c;, b и c могут быть почти полностью произвольные типы. + может быть реализована как функция-член типа b или может быть свободной функцией. В некоторых случаях у нас может быть несколько перегруженных операторов (некоторые из которых могут быть шаблонами), которые могут выполнять эту операцию, поэтому нам нужно выполнить разрешение перегрузки, чтобы определить, какой из них компилятор фактически выберет на основе на типах параметров (и если некоторые из них являются шаблонами, правила разрешения перегрузки становятся еще более сложными).

Это позволяет нам определить тип результата из b + c. Оттуда мы в основном повторяем весь процесс снова, чтобы выяснить, какая (если есть) перегрузка используется для присвоения этого результата a. Он может быть встроенным, или это может быть другая перегрузка оператора, и может быть несколько возможных перегрузок, которые могли бы выполнить эту работу, поэтому нам нужно снова выполнить разрешение перегрузки, чтобы выяснить, какой оператор использовать здесь.

Короче говоря, просто для того, чтобы понять, что означает a = b + c; в C++, требуется почти весь внешний интерфейс компилятора.Мы можем сделать то же самое в Java с намного меньшим подмножеством компилятора2


  1. Я полагаю, что все могло бы быть несколько иначе, если бы вы разрешили перегрузку операторов, как это делает, например, ML, где более или менее произвольный токен может быть обозначен как оператор, и этому оператору может быть присвоена более или менее произвольная ассоциативность и/или приоритет. Я полагаю, что ML обрабатывает это полностью с помощью синтаксического анализа, а не лексического анализа, но если вы продвинетесь в этой базовой концепции достаточно дальше, я могу поверить, что это может начать влиять на лексический анализ, а не только на синтаксический анализ.
  2. Не говоря уже о том, что большинство инструментов Java будут использовать JDK, который имеет полный компилятор Java, встроенный в JVM, поэтому инструменты обычно могут выполнять большую часть такого анализа, не занимаясь непосредственно синтаксическим анализом и вообще подобным.
5
ответ дан 30 November 2019 в 11:07
поделиться

Отметьте Функции Java удалены из C и C++ стр. 2.2.7 Больше не будет перегружаться оператором.

Не предусмотрено средств, с помощью которых программисты могут перегрузить стандартный арифметические операторы. Еще раз, последствия перегрузки оператора могут быть так же легко достигается путем объявления класс, соответствующие переменные экземпляра, и соответствующие методы манипулирования эти переменные. Исключающий оператор перегрузка приводит к большим упрощение кода.

0
ответ дан 30 November 2019 в 11:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: