Почему Java не предлагает перегрузку операторов?

Из официальной документации :

QtConcurrent :: run () также принимает указатели на функции-члены. Первый аргумент должен быть либо ссылкой на константу, либо указателем на экземпляр класса. Передача с помощью ссылки const полезна при вызове функций-членов-членов; прохождение по указателю полезно для вызова неконстантных функций-членов, которые изменяют экземпляр.

blockquote>

У вас есть указатель на указатель. Также обратите внимание, что вы не можете передавать аргументы так, как вы это делаете, а как дополнительные аргументы в функции run. Следующее должно работать:

futureComput = QtConcurrent::run(this->myMgr,&Manager::compute, model);

391
задан 9 revs, 7 users 47%rengolin 20 April 2018 в 10:04
поделиться

12 ответов

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

Complex a, b, c;
// ...
a = b.add(c);

В C++, это выражение говорит компилятору создавать три (3) объекта на стеке, выполнять дополнение, и копия результирующее значение от временного объекта в существующий объект a.

Однако в Java, operator= не выполняет копию значения для ссылочных типов, и пользователи могут только создать новые ссылочные типы, не оценить типы. Таким образом для пользовательского типа, названного Complex, присвоение означает копировать ссылку на существующее значение.

Рассматривают вместо этого:

b.set(1, 0); // initialize to real number '1'
a = b; 
b.set(2, 0);
assert( !a.equals(b) ); // this assertion will fail

В C++, это копирует значение, таким образом, сравнение закончится не - равный. В Java, operator= выполняет ссылочную копию, таким образом a и b теперь относятся к тому же значению. В результате сравнение произведет 'равный', так как объект выдержит сравнение равный себе.

различие между копиями и ссылками только добавляет к беспорядку перегрузки оператора. Поскольку упомянутые @Sebastian, Java и C# и должны иметь дело со значением и ссылочным равенством отдельно - operator+, вероятно, имел бы дело со значениями и объектами, но operator= уже реализован для контакта со ссылками.

В C++, необходимо только иметь дело с одним видом сравнения за один раз, таким образом, это может менее сбивать с толку. Например, на [1 111], operator= и operator== и работают над значениями - копирование значений и сравнение значений соответственно.

15
ответ дан rrauenza 20 April 2018 в 20:04
поделиться

Иногда было бы хорошо иметь перегрузку оператора, друг классы и множественное наследование.

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

// a = b + c
Complex a, b, c; a = b.add(c);
1
ответ дан 20 April 2018 в 20:04
поделиться
  • 1
    @Sandy I' m защита, что блоки являются хорошим способом поставить результаты определенных действий, но плохой основы для более общего разговора. Обеспечение блока похоже на слушателя, говорящего ' это - то, как Вы говорите с me'; протокол делегата похож на говорящего, говорящего ' это - то, как я буду говорить с you'. если говорящий главным образом решает, когда говорить тогда, это должно продиктовать, как это говорит. Если слушатель просто просит, чтобы определенная вещь была сделана и результаты, о которых сообщают тогда, она имеет смысл, что она говорит '... и сообщите как this'. – Tommy 29 May 2013 в 08:18

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

6
ответ дан user14128 20 April 2018 в 20:04
поделиться
  • 1
    Вы хотите знать, потому что you' ре, пытающееся отладить Ваше приложение. Вы can' t говорят кому-то, " Вы don' t должен знать, потому что необходимо просто сделать его правильно, в этом случае Вы won' t care". возможно, они shouldn' t нужен код в их производственном выпуске, но that' s не то же самое как не бывший должный знать касательно количества, как инструмент отлаживать, почему you' ре, имеющее проблемы. Плохой ответ. – Nate 4 August 2010 в 12:34

James Gosling уподобил Java разработки следующему:

"существует этот принцип о перемещении, когда Вы перемещаетесь от одной квартиры до другой квартиры. Интересный эксперимент должен собрать Вашу квартиру и поместить все в поля, затем переместиться в следующую квартиру и не распаковать что-либо, пока Вам не нужен он. Таким образом, Вы готовите свое первое блюдо, и Вы вытаскиваете что-то из поля. Затем приблизительно после одного месяца Вы использовали это, чтобы в значительной степени выяснить, в каких вещах в Вашей жизни Вы на самом деле нуждаетесь, и затем Вы берете остальную часть материала - забывают, насколько Вам нравится он или насколько прохладный это - и Вы просто выбрасываете его. Удивительно, как это упрощает Вашу жизнь, и можно использовать тот принцип во всех видах вопросов проектирования: не делают вещи просто, потому что они прохладны или просто потому что они интересны".

можно читать контекст кавычки здесь

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

Другим фактором было злоупотребление функцией в C++ операторами перегрузки разработчиков как '& &'; '||', операторы броска и конечно 'новый'. Сложность, следующая из объединения этого с передачей значением и исключениями, хорошо покрыта в Исключительный C++ книга.

42
ответ дан Garth Gilmour 20 April 2018 в 20:04
поделиться

Groovy имеет перегрузку оператора и работает в JVM. Если Вы не возражаете против хита производительности (который становится меньшим повседневный). Это автоматически на основе имен методов. например, '+' звонит 'плюс (аргумент)' метод.

8
ответ дан noah 20 April 2018 в 20:04
поделиться

Повышение выезда. Единицы: текст ссылки

Это обеспечивает служебный нулем Размерный анализ посредством перегрузки оператора. Насколько более ясный это может добраться?

quantity<force>     F = 2.0*newton;
quantity<length>    dx = 2.0*meter;
quantity<energy>    E = F * dx;
std::cout << "Energy = " << E << endl;

на самом деле произвел бы "энергию = 4 Дж", который корректен.

22
ответ дан user15793 20 April 2018 в 20:04
поделиться
  • 1
    Этому методу препятствуют, чтобы использоваться и даже не гарантироваться возвратить корректное число. – Eonil 4 August 2012 в 20:12

Разработчики Java решили, что перегрузка оператора была большей проблемой, чем это стоило. Простой как это.

На языке, где каждая переменная объекта является на самом деле ссылкой, перегрузка оператора получает дополнительную опасность того, чтобы быть довольно нелогичным - программисту на C++, по крайней мере. Сравните ситуацию с C# == перегрузка оператора и Object.Equals и Object.ReferenceEquals (или независимо от того, что это называют).

12
ответ дан Azeem 20 April 2018 в 20:04
поделиться
  • 1
    Don' t понимают меня превратно. Инструменты являются большими. Но, это имеет ограничения и there' s никакая причина разработчик должен быть ограничен просто использованием Инструментов. Что, если проблема doesn' t неожиданно возникают в Вашей настольной тестовой среде? Что, если Вы хотите развернуть устройства на поле и использование, регистрирующееся, чтобы дать Вам что-то для анализа позже? Или возможно there' s что-то основанное на местоположении о Вашем приложении, или о проблемном коде, который требует Вас вынимающий устройство из Вашего офиса. Вы не можете быть в состоянии принести свою рабочую станцию разработки в поле. Плакат doesn' t должен выровнять по ширине задавание вопроса. – Nate 21 April 2011 в 20:40

Принимая Java как язык реализации затем a, b, и c все был бы ссылками для ввода Комплекса с начальными значениями пустого указателя. Также предполагая, что Комплекс неизменен как упомянутый BigInteger и подобный неизменный BigDecimal, я был бы я думать, что Вы имеете в виду следующее, поскольку Вы присваиваете ссылку на Комплекс, возвращенный из добавления b и c и не сравнения этой ссылки на a.

Не:

Complex a, b, c; a = b + c;

очень более простой, чем:

Complex a, b, c; a = b.add(c);
2
ответ дан David Schlosnagle 20 April 2018 в 20:04
поделиться

Хорошо можно действительно выстрелить себе в ногу с перегрузкой оператора. Это похоже с людьми указателей, делают глупые ошибки с ними и таким образом, было решено убрать ножницы.

, По крайней мере, я думаю, что это - причина. Я нахожусь на Вашей стороне так или иначе. :)

5
ответ дан Sarien 20 April 2018 в 20:04
поделиться
  • 1
    Там какое-либо преимущество к использованию синтезируемого метода set по сравнению с подходом, предложенным @Renger? – Madbreaks 20 December 2012 в 07:23

Существует много сообщений, жалующихся на перегрузку оператора.

я чувствовал, что должен был разъяснить "оператор, перегружающий" понятия, предложив альтернативную точку зрения на это понятие.

запутывание Кода?

Этим аргументом является ошибка.

Запутывание возможно на всех языках...

столь же легко запутать код в C или Java через функции/методы, как это находится в C++ посредством перегрузок оператора:

// C++
T operator + (const T & a, const T & b) // add ?
{
   T c ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

// Java
static T add (T a, T b) // add ?
{
   T c = new T() ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

/* C */
T add (T a, T b) /* add ? */
{
   T c ;
   c.value = a.value - b.value ; /* subtract !!! */
   return c ;
}

... Даже в стандартных интерфейсах Java

Для другого примера, давайте посмотрим Cloneable интерфейс в Java:

Вы, как предполагается, клонируете объект, реализовывая этот интерфейс. Но Вы могли лгать. И создайте другой объект. На самом деле этот интерфейс так слаб, Вы могли возвратить другой тип объекта в целом, просто ради удовольствия:

class MySincereHandShake implements Cloneable
{
    public Object clone()
    {
       return new MyVengefulKickInYourHead() ;
    }
}

Как эти Cloneable интерфейс может быть оскорблен/запутан, он должен быть запрещен на том же основании, перегрузка оператора C++, как предполагается?

Мы могли перегрузиться toString() метод MyComplexNumber, класс, чтобы иметь его возвращает stringified час дня. toString() перегрузка должна быть запрещена, также? Мы могли саботировать MyComplexNumber.equals, чтобы иметь его, возвращают случайное значение, изменяют операнды... и т.д. и т.д. и т.д.

В Java, как в C++, или безотносительно языка, программист должен уважать минимум семантики когда написание кода. Это означает реализовывать add функция, которая добавляет, и Cloneable метод внедрения, который клонируется, и ++ оператор, чем инкременты.

, Что запутывает так или иначе?

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

Четкая и естественная нотация: методы по сравнению с перегрузкой оператора?

Мы выдержим сравнение ниже, для различных случаев, "того же" кода в Java и C++, чтобы иметь идею, от которой вид стиля кодирования более свободен.

Естественные сравнения:

// C++ comparison for built-ins and user-defined types
bool    isEqual          = A == B ;
bool    isNotEqual       = A != B ;
bool    isLesser         = A <  B ;
bool    isLesserOrEqual  = A <= B ;

// Java comparison for user-defined types
boolean isEqual          = A.equals(B) ;
boolean isNotEqual       = ! A.equals(B) ;
boolean isLesser         = A.comparesTo(B) < 0 ;
boolean isLesserOrEqual  = A.comparesTo(B) <= 0 ;

Обратите внимание на то, что A и B мог иметь любой тип в C++, пока перегрузки оператора обеспечиваются. В Java, когда A и B не являются примитивами, код может стать очень сбивающим с толку, даже для подобных примитиву объектов (BigInteger, и т.д.)...

Естественные средства доступа массива/контейнера и индексирование:

// C++ container accessors, more natural
value        = myArray[25] ;         // subscript operator
value        = myVector[25] ;        // subscript operator
value        = myString[25] ;        // subscript operator
value        = myMap["25"] ;         // subscript operator
myArray[25]  = value ;               // subscript operator
myVector[25] = value ;               // subscript operator
myString[25] = value ;               // subscript operator
myMap["25"]  = value ;               // subscript operator

// Java container accessors, each one has its special notation
value        = myArray[25] ;         // subscript operator
value        = myVector.get(25) ;    // method get
value        = myString.charAt(25) ; // method charAt
value        = myMap.get("25") ;     // method get
myArray[25]  = value ;               // subscript operator
myVector.set(25, value) ;            // method set
myMap.put("25", value) ;             // method put

В Java, мы видим, что, чтобы каждый контейнер сделал то же самое (получают доступ к его содержанию через индекс или идентификатор), у нас есть различный способ сделать это, который сбивает с толку.

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

Естественное усовершенствованное управление типами

примеры ниже используют Matrix объект, найденный использованием первых ссылок, найденных на Google для" объект Матрицы Java " и" объект Матрицы C++ ":

// C++ YMatrix matrix implementation on CodeProject
// http://www.codeproject.com/KB/architecture/ymatrix.aspx
// A, B, C, D, E, F are Matrix objects;
E =  A * (B / 2) ;
E += (A - B) * (C + D) ;
F =  E ;                  // deep copy of the matrix

// Java JAMA matrix implementation (seriously...)
// http://math.nist.gov/javanumerics/jama/doc/
// A, B, C, D, E, F are Matrix objects;
E = A.times(B.times(0.5)) ;
E.plusEquals(A.minus(B).times(C.plus(D))) ;
F = E.copy() ;            // deep copy of the matrix

И это не ограничено матрицами. BigInteger и BigDecimal классы Java страдают от того же запутывающего многословия, тогда как их эквиваленты в C++ так же ясны как встроенные типы.

Естественные итераторы:

// C++ Random Access iterators
++it ;                  // move to the next item
--it ;                  // move to the previous item
it += 5 ;               // move to the next 5th item (random access)
value = *it ;           // gets the value of the current item
*it = 3.1415 ;          // sets the value 3.1415 to the current item
(*it).foo() ;           // call method foo() of the current item

// Java ListIterator<E> "bi-directional" iterators
value = it.next() ;     // move to the next item & return the value
value = it.previous() ; // move to the previous item & return the value
it.set(3.1415) ;        // sets the value 3.1415 to the current item

Естественные функторы:

// C++ Functors
myFunctorObject("Hello World", 42) ;

// Java Functors ???
myFunctorObject.execute("Hello World", 42) ;

текстовая конкатенация:

// C++ stream handling (with the << operator)
                    stringStream   << "Hello " << 25 << " World" ;
                    fileStream     << "Hello " << 25 << " World" ;
                    outputStream   << "Hello " << 25 << " World" ;
                    networkStream  << "Hello " << 25 << " World" ;
anythingThatOverloadsShiftOperator << "Hello " << 25 << " World" ;

// Java concatenation
myStringBuffer.append("Hello ").append(25).append(" World") ;

хорошо, в Java можно использовать MyString = "Hello " + 25 + " World" ; также... Но, ожидайте секунда: Это - перегрузка оператора, не так ли? Разве это не обман???

:-D

Общий код?

тот же общий код, изменяющий операнды, должен быть применимым оба для built-ins/primitives (которые не имеют никаких интерфейсов в Java), стандартные объекты (который не мог иметь правильного интерфейса), и пользовательские объекты.

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

// C++ primitive/advanced types
template<typename T>
T getAverage(const T & p_lhs, const T & p_rhs)
{
   return (p_lhs + p_rhs) / 2 ;
}

int     intValue     = getAverage(25, 42) ;
double  doubleValue  = getAverage(25.25, 42.42) ;
complex complexValue = getAverage(cA, cB) ; // cA, cB are complex
Matrix  matrixValue  = getAverage(mA, mB) ; // mA, mB are Matrix

// Java primitive/advanced types
// It won't really work in Java, even with generics. Sorry.

оператор Discussing, перегружающийся

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

перегрузка Оператора существовала еще до компьютеров

Даже за пределами информатики, существует перегрузка оператора: Например, в математике, операторы как [1 122], -, *, и т.д. перегружаются.

Действительно, значение [1 125], -, *, и т.д. изменяется в зависимости от типов операндов (численные данные, векторы, квантовые волновые функции, матрицы, и т.д.).

Большинство из нас, как часть наших научных курсов, изучило несколько значений для операторов, в зависимости от типов операндов. Мы находили их сбивающими с толку, их?

перегрузка Оператора зависит от своих операндов

, Это - самая важная часть перегрузки оператора: Как в математике, или в физике, операция зависит от типов своих операндов.

Так, знайте тип операнда, и Вы будете знать эффект операции.

Даже C и Java (трудно кодировали) оператор, перегружающийся

В C, реальное поведение оператора изменится согласно его операндам. Например, добавление двух целых чисел отличается, чем добавление два удваивается, или даже одно целое число и одно двойное. Существует даже целый домен адресной арифметики с указателями (без кастинга, можно добавить к указателю целое число, но Вы не можете добавить два указателя...).

В Java, нет никакой адресной арифметики с указателями, но кто-то все еще нашел конкатенацию строк без +, оператор будет достаточно смешон выровнять по ширине исключение в "перегрузке оператора, злое" кредо.

Это просто, что Вы, как C (по историческим причинам) или Java (для [1 195] личные мотивы , видят ниже), кодер, Вы не можете обеспечить свое собственное.

В C++, перегрузка оператора не является дополнительной...

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

, Как уже сказано ранее, в C++, и об обратном к Java, пользовательские типы не считают второразрядными гражданами языка, по сравнению со встроенными типами. Так, если встроенные типы имеют операторы, пользовательские типы должны смочь иметь их, также.

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

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

..., но этим нельзя злоупотребить

, перегрузка Оператора должна стремиться уважать семантику оператора. Не вычитайте в + оператор (поскольку в "не вычитают в add, функция", или "возвращают дерьмо в clone метод").

перегрузка Броска может быть очень опасной, потому что они могут привести к неоднозначностям. Таким образом, они должны действительно быть зарезервированы для четко определенных случаев. Что касается [1 135] и ||, никогда не перегружайте их, если Вы действительно не знаете то, что Вы делаете, поскольку Вы потеряете оценку короткого замыкания, которой обладают собственные операторы && и ||.

Так... Хорошо... Затем, почему это не возможно в Java?

, поскольку James Gosling сказал так:

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

James Gosling. Источник: http://www.gotw.ca/publications/c_family_interview.htm

сравните текст Gosling выше с Stroustrup ниже:

Много проектных решений C++ имеют свои корни в моей неприязни к тому, чтобы вынуждать людей делать вещи некоторым конкретным способом [...] Часто, я испытал желание запретить функцию, которую я лично не любил, я воздержался от выполнения поэтому, потому что я не думал, что имел право вызвать мои представления о других .

Bjarne Stroustrup. Источник: Desing и Эволюция C++ (1.3 Общих Фона)

оператор Would, перегружающий Java преимущества?

Некоторые объекты значительно извлекли бы выгоду из перегрузки оператора (конкретные или числовые типы, как BigDecimal, комплексные числа, матрицы, контейнеры, итераторы, компараторы, синтаксические анализаторы и т.д.).

В C++, можно получить прибыль от этого преимущества из-за смирения Stroustrup. В Java Вы просто завинчены из-за Gosling личный выбор .

это могло быть добавлено к Java?

причинами того, что не был добавлен оператор, перегружающийся теперь в Java, могло быть соединение внутренней политики, аллергии на функцию, недоверие к разработчикам (Вы знаете, саботажника, которые, кажется, преследуют команды Java...), совместимость с предыдущим JVMs, время для записи корректной спецификации, и т.д.

Так не задерживают Ваше дыхание, ожидающее этой функции...

, Но они делают это в C#!!!

Да...

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

, По-видимому, люди C#, с их "каждый примитив struct, и struct происходит из Объекта" , разобрался в нем при первой попытке.

И они делают это в [1 145] другие языки !!!

Несмотря на весь FUD против используемой определенной перегрузки оператора, следующие языки поддерживают его: Scala, Dart, Python , F# , C#, D, Алгол 68 , Smalltalk, Groovy, Perl 6, C++, Ruby, Haskell, MATLAB, Eiffel, Lua, Clojure, Фортран 90 , Swift, Ada, Delphi 2005 ...

Столько языков, с так многими отличающимися (и иногда выступающий) основные положения, и все же они все приходят к соглашению по тому вопросу.

Пища для размышления...

764
ответ дан 24 revs, 8 users 97% 20 April 2018 в 20:04
поделиться
  • 1
    Это смотрит хорошее обходное решение. Спасибо. – awsome 29 April 2010 в 22:30

Сказать, что перегрузка оператора приводит к логическим ошибкам типа, что оператор не соответствует логике работы, это все равно что ничего не сказать. Тот же тип ошибки произойдет, если имя функции не подходит для логики работы - так что же решение: отказаться от возможности использования функции !? Это комичный ответ - «Не подходит для логики работы», каждое имя параметра, каждый класс, функция или что-то еще может быть логически несоответствующим. Я думаю, что эта опция должна быть доступна на респектабельном языке программирования, а те, кто думают, что это небезопасно - нет, оба говорят, что вы должны ее использовать. Возьмем C #. Они опустили указатели, но эй - есть инструкция «небезопасный код» - программируйте как хотите на свой страх и риск.

4
ответ дан 22 November 2019 в 23:44
поделиться

Некоторые люди говорят, что перегрузка операторов в Java приведет к запутыванию. Эти люди когда-нибудь останавливались, чтобы посмотреть на какой-нибудь Java-код, выполняющий некоторые базовые математические операции, такие как увеличение финансовой стоимости на процент с помощью BigDecimal? .... многословие такого упражнения становится демонстрацией запутанности.Как ни странно, добавление перегрузки операторов в Java позволило бы нам создать наш собственный класс Currency, который сделал бы такой математический код элегантным и простым (менее запутанным).

5
ответ дан 22 November 2019 в 23:44
поделиться
Другие вопросы по тегам:

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