it-swarm-eu.dev

Warum bietet Java keine Überladung von Operatoren?

Die offensichtliche unbeantwortete Frage, die von C++ zu Java kommt, ist die Frage, warum Java keine Operatorüberladung enthielt.

Ist Complex a, b, c; a = b + c; nicht viel einfacher als Complex a, b, c; a = b.add(c);?

Gibt es einen bekannten Grund dafür, gültige Argumente für nicht , die eine Überladung des Operators zulassen? Ist der Grund willkürlich oder geht der Zeit verloren?

375
rengolin

Angenommen, Sie wollten den vorherigen Wert des Objekts, auf das mit a verwiesen wird, überschreiben, müsste eine Member-Funktion aufgerufen werden.

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

In C++ weist dieser Ausdruck den Compiler an, drei (3) Objekte auf dem Stack zu erstellen, eine Addition durchzuführen und copy den resultierenden Wert aus dem temporären Objekt in das vorhandene Objekt a zu kopieren.

In Java führt operator= jedoch keine Wertkopie für Referenztypen durch, und Benutzer können nur neue Referenztypen und keine Werttypen erstellen. Bei einem benutzerdefinierten Typ mit dem Namen Complex bedeutet Zuweisung das Kopieren einer Referenz auf einen vorhandenen Wert.

Betrachten Sie stattdessen:

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

In C++ wird der Wert kopiert, sodass der Vergleich nicht gleich ist. In Java führt operator= eine Referenzkopie durch, sodass a und b jetzt auf denselben Wert verweisen. Als Ergebnis wird der Vergleich "gleich" erzeugen, da das Objekt sich selbst gleich vergleicht.

Der Unterschied zwischen Kopien und Verweisen trägt nur zur Verwirrung der Überladung des Bedieners bei. Wie bei @Sebastian erwähnt, müssen Java und C # beide die Wert- und Referenzgleichheit separat behandeln. operator+ würde sich wahrscheinlich mit Werten und Objekten befassen, operator= ist jedoch bereits für die Verarbeitung von Referenzen implementiert.

In C++ sollten Sie sich immer nur mit einer Art von Vergleich befassen, sodass es weniger verwirrend ist. Bei Complex arbeiten operator= und operator== beide an Werten - Werte kopieren bzw. Werte vergleichen.

17
Aaron

Es gibt viele Beiträge, die sich über das Überladen von Operatoren beschweren.

Ich hatte das Gefühl, dass ich die Konzepte der "Bedienerüberladung" klären musste, um einen alternativen Standpunkt zu diesem Konzept zu bieten.

Code verschleiert?

Dieses Argument ist ein Irrtum.

Verschleierung ist in allen Sprachen möglich ...

Es ist so einfach, Code in C oder Java durch Funktionen/Methoden zu verschleiern wie in C++ durch Überladungen von Operatoren:

// 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 ;
}

... auch in Javas Standardschnittstellen

Ein anderes Beispiel ist die Schnittstelle CloneableNAME_ in Java:

Sie sollen das Objekt klonen, das diese Schnittstelle implementiert. Aber du könntest lügen. Und ein anderes Objekt erstellen. Tatsächlich ist diese Schnittstelle so schwach, dass Sie nur zum Spaß einen anderen Objekttyp zurückgeben können:

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

Da die Schnittstelle Cloneablemissbraucht/verschleiert werden kann, sollte sie aus den gleichen Gründen gesperrt werden, aus denen das Überladen von C++ - Operatoren erfolgen soll.

Wir könnten die toString() -Methode einer MyComplexNumber-Klasse überladen, damit sie die angegebene Stunde des Tages zurückgibt. Sollte die toString() Überladung auch verboten werden? Wir könnten MyComplexNumber.equals sabotieren, damit er einen zufälligen Wert zurückgibt, die Operanden ändern ... usw. usw. usw.

In Java wie in C++ oder in einer anderen Sprache muss der Programmierer beim Schreiben von Code ein Minimum an Semantik berücksichtigen. Dies bedeutet, dass eine addname__-Funktion implementiert wird, die hinzugefügt wird, sowie eine Cloneablename__-Implementierungsmethode, die geklont wird, und ein ++ -Operator als Inkremente.

Was ist überhaupt verschleiert?

Nachdem wir nun wissen, dass Code auch mit den unberührten Methoden Java sabotiert werden kann, können wir uns fragen, wie das Überladen von Operatoren in C++ wirklich funktioniert.

Klare und natürliche Notation: Methoden vs. Bedienerüberladung?

Wir werden unten für verschiedene Fälle den "gleichen" Code in Java und C++ vergleichen, um eine Vorstellung davon zu bekommen, welche Art von Codierungsstil klarer ist.

Natürliche Vergleiche:

// 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 ;

Bitte beachten Sie, dass A und B in C++ von jedem Typ sein können, solange die Operatorüberladungen bereitgestellt werden. Wenn in Java A und B keine Grundelemente sind, kann der Code sehr verwirrend werden, selbst für primitivähnliche Objekte (BigInteger usw.).

Natürliche Array-/Container-Accessoren und Subskription:

// 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

In Java sehen wir, dass jeder Container das Gleiche tut (Zugriff auf seinen Inhalt über einen Index oder einen Bezeichner), was verwirrend ist.

In C++ greift jeder Container dank der Überladung von Operatoren auf die gleiche Weise auf seinen Inhalt zu.

Natürliche Manipulation fortgeschrittener Typen

In den folgenden Beispielen wird ein Matrixname__-Objekt verwendet, das über die ersten Links in Google für " Java Matrix-Objekt " und " c ++ Matrix-Objekt " gefunden wurde:

// 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

Und das ist nicht auf Matrizen beschränkt. Die Klassen BigIntegerund BigDecimalvon Java leiden unter derselben verwirrenden Ausführlichkeit, während ihre Entsprechungen in C++ so klar sind wie die von integrierten Typen.

Natürliche Iteratoren:

// 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

Natürliche functors:

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

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

Textverkettung:

// 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") ;

Ok, in Java können Sie MyString = "Hello " + 25 + " World" ; auch verwenden ... Aber warten Sie eine Sekunde: Dies ist eine Überladung des Operators, nicht wahr? Betrügt es nicht ???

:-D

Generischer Code?

Dieselben generischen Code-Änderungsoperanden sollten sowohl für integrierte Elemente/Grundelemente (die in Java keine Schnittstellen haben) als auch für Standardobjekte (die möglicherweise nicht die richtige Schnittstelle haben) und für benutzerdefinierte Objekte verwendbar sein.

Berechnen Sie beispielsweise den Durchschnittswert von zwei Werten beliebigen Typs:

// 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.

Diskussion über die Überlastung des Operators

Nachdem wir nun faire Vergleiche zwischen C++ - Code mit Operatorüberladung und demselben Code in Java gesehen haben, können wir nun das Konzept der "Operatorüberladung" diskutieren.

Operatorüberladung bestand seit vor Computern

Auch außerhalb der Informatik gibt es eine Überladung von Operatoren: In der Mathematik sind beispielsweise Operatoren wie +, -, * usw. überladen.

In der Tat ändert sich die Bedeutung von +, -, * usw. in Abhängigkeit von den Typen der Operanden (Zahlen, Vektoren, Quantenwellenfunktionen, Matrizen usw.).

Die meisten von uns haben im Rahmen ihrer naturwissenschaftlichen Kurse je nach Art der Operanden mehrere Bedeutungen für Operatoren gelernt. Fanden wir sie verwirrend, sie?

Die Überladung von Operatoren hängt von ihren Operanden ab

Dies ist der wichtigste Teil der Überladung von Operatoren: Wie in der Mathematik oder in der Physik hängt die Operation von den Typen der Operanden ab.

Kennen Sie also den Typ des Operanden, und Sie werden die Auswirkung der Operation kennen.

Sogar C und Java weisen eine (fest codierte) Überladung der Operatoren auf

In C ändert sich das tatsächliche Verhalten eines Operators entsprechend seiner Operanden. Das Hinzufügen von zwei Ganzzahlen unterscheidet sich beispielsweise vom Hinzufügen von zwei Doppelwerten oder sogar einer Ganzzahl und einem Doppelwert. Es gibt sogar den gesamten Bereich der Zeigerarithmetik (ohne Casting können Sie einem Zeiger eine Ganzzahl hinzufügen, aber Sie können nicht zwei Zeiger hinzufügen ...).

In Java gibt es keine Zeigerarithmetik, aber jemand, der die Verkettung von Zeichenfolgen ohne den Operator + gefunden hat, wäre lächerlich genug, um eine Ausnahme im Credo "Überladen von Operatoren ist böse" zu rechtfertigen.

Es ist nur so, dass Sie als C (aus historischen Gründen) oder Java (für persönliche Gründe(siehe unten) coder, du kannst keinen eigenen bereitstellen.

In C++ ist das Überladen von Operatoren nicht optional ...

In C++ ist das Überladen von Operatoren für integrierte Typen nicht möglich (und das ist gut so), aber benutzerdefinierten Typen können haben benutzerdefinierten Bedienerüberlastungen.

Wie bereits erwähnt, werden Benutzertypen in C++ und im Gegensatz zu Java im Vergleich zu integrierten Typen nicht als zweitklassige Staatsbürger der Sprache betrachtet. Wenn integrierte Typen Operatoren haben, sollten diese auch für Benutzertypen verfügbar sein.

Die Wahrheit ist, dass, wie die toString(), clone(), equals() Methoden für Java sind (quasi-Standard-ähnlich) Ist das Überladen von C++ - Operatoren ein so großer Teil von C++, dass es genauso selbstverständlich wird wie die ursprünglichen C-Operatoren oder die zuvor erwähnten Java -Methoden.

In Kombination mit der Vorlagenprogrammierung wird das Überladen von Operatoren zu einem bekannten Entwurfsmuster. Tatsächlich können Sie in STL nicht sehr weit gehen, ohne überladene Operatoren und Überladungsoperatoren für Ihre eigene Klasse zu verwenden.

... aber es sollte nicht missbraucht werden

Das Überladen von Operatoren sollte sich bemühen, die Semantik des Operators zu respektieren. Subtrahieren Sie nicht in einem + -Operator (wie in "Subtrahieren Sie nicht in einer add-Funktion" oder "Zurückgeben von Mist in einer clone-Methode").

Cast-Überladung kann sehr gefährlich sein, da sie zu Mehrdeutigkeiten führen kann. Sie sollten also wirklich für genau definierte Fälle reserviert sein. Überlasten Sie && und || nur, wenn Sie wirklich wissen, was Sie tun, da Sie die Kurzschlussbewertung verlieren, die die nativen Operatoren && und || genießen.

Also ... Ok ... Warum ist es dann in Java nicht möglich?

Weil James Gosling so sagte:

Ich habe das Überladen des Operators ausgelassen als ziemlich persönliche Wahl weil ich zu viele Leute gesehen hatte, die es in C++ missbraucht haben.

James Gosling. Quelle: http://www.gotw.ca/publications/c_family_interview.htm

Bitte vergleichen Sie Goslings Text oben mit dem von Stroustrup unten:

Viele C++ - Entwurfsentscheidungen haben ihre Wurzeln in meiner Abneigung, Menschen dazu zu zwingen, bestimmte Dinge zu tun. [...] Oft war ich versucht, ein Feature zu verbieten, das mir persönlich nicht gefiel, und ich habe es deshalb unterlassen Ich dachte nicht, dass ich das Recht hätte, meine Ansichten anderen aufzuzwingen.

Bjarne Stroustrup. Quelle: Das Entwerfen und Entwickeln von C++ (1.3 Allgemeiner Hintergrund)

Würde eine Überlastung des Operators Java zugute kommen?

Einige Objekte würden von einer Überladung des Operators stark profitieren (konkrete oder numerische Typen wie BigDecimal, komplexe Zahlen, Matrizen, Container, Iteratoren, Komparatoren, Parser usw.).

In C++ können Sie aufgrund der Demut von Stroustrup von diesem Vorteil profitieren. In Java sind Sie einfach wegen Gänschen geschraubt persönliche Wahl.

Könnte es zu Java hinzugefügt werden?

Die Gründe, warum in Java keine Operatorüberladung hinzugefügt wurde, könnten eine Mischung aus interner Politik, Allergie gegen das Feature und Misstrauen gegenüber Entwicklern sein (Sie wissen, die Saboteure, die Java zu verfolgen scheinen). Teams ...), Kompatibilität mit den vorherigen JVMs, Zeit zum Schreiben einer korrekten Spezifikation, etc ..

Halten Sie also nicht den Atem an und warten Sie auf diese Funktion ...

Aber sie machen es in C # !!!

Ja...

Das ist bei weitem nicht der einzige Unterschied zwischen den beiden Sprachen, aber dieser amüsiert mich immer wieder.

Anscheinend sind die C # Leute mit ihren "Jedes Grundelement ist ein structname__, und ein structleitet sich von Object ab."Habe es gleich beim ersten Versuch richtig gemacht.

Und sie tun es in anderen Sprachen !!!

Trotz aller FUD gegen das verwendete Überladen von definierten Operatoren unterstützen die folgenden Sprachen dies: Scala , Dart , Python , F # =, C # , D , ALGOL 68 , Smalltalk , Groovy , Perl 6 , C++, Ruby , Haskell , MATLAB , Eiffel , Lua , Clojure , Fortran 9 , Swift , Ada , Delphi 2005 ...

So viele Sprachen mit so vielen unterschiedlichen (und manchmal gegensätzlichen) Philosophien, und doch sind sich alle in diesem Punkt einig.

Denkanstöße ...

760
paercebal

James Gosling verglich das Entwerfen von Java mit Folgendem:

"Es gibt dieses Prinzip beim Umzug, wenn Sie von einer Wohnung in eine andere umziehen. Ein interessantes Experiment besteht darin, Ihre Wohnung einzupacken und alles in Kisten zu packen, dann in die nächste Wohnung zu ziehen und nichts auszupacken, bevor Sie es nicht brauchen. Sie bereiten Ihre erste Mahlzeit zu, und Sie ziehen etwas aus einer Kiste, und dann haben Sie nach etwa einem Monat so ziemlich herausgefunden, welche Dinge in Ihrem Leben Sie wirklich brauchen, und dann nehmen Sie den Rest des Essens Zeug - vergiss, wie sehr du es magst oder wie cool es ist - und du wirfst es einfach weg. Es ist erstaunlich, wie das dein Leben vereinfacht, und du kannst dieses Prinzip in allen möglichen Designfragen anwenden: Dinge nicht einfach nur tun, weil sie es tun bist cool oder nur weil sie interessant sind. "

Den Kontext des Zitats können Sie hier lesen

Grundsätzlich ist das Überladen von Operatoren ideal für eine Klasse, die eine bestimmte Punkt-, Währungs- oder komplexe Zahl modelliert. Aber danach laufen dir die Beispiele schnell aus.

Ein weiterer Faktor war der Missbrauch des Features in C++ durch Entwickler, die Operatoren wie '&&', '||', die Cast-Operatoren und natürlich 'new' überladen. Die Komplexität, die sich aus der Kombination dieser Werte mit Ausnahmen und Ausnahmen ergibt, wird im Exceptional C++ book gut abgedeckt.

39
Garth Gilmour

Check out Boost.Units: Linktext

Es bietet eine Null-Overhead-Dimensionsanalyse durch Überlastung des Bedieners. Wie viel klarer kann das werden?

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

würde tatsächlich "Energy = 4 J" ausgeben, was korrekt ist.

20
user15793

Die Java-Designer entschieden, dass das Überladen von Operatoren mehr Probleme bereitet, als es wert war. So einfach ist das.

In einer Sprache, in der jede Objektvariable tatsächlich eine Referenz ist, besteht für das Überladen von Operatoren die zusätzliche Gefahr, dass sie ziemlich unlogisch ist - zumindest für einen C++ - Programmierer. Vergleichen Sie die Situation mit dem Überladen des Operators == und Object.Equals und Object.ReferenceEquals (oder wie auch immer es genannt wird).

11
Sebastian Redl

Groovy hat Operatorüberladung und läuft in der JVM. Wenn Sie nichts dagegen haben, ist der Performance-Hit (der jeden Tag kleiner wird). Es basiert automatisch auf Methodennamen. Beispielsweise ruft '+' die Methode 'plus (Argument)' auf.

8
noah

Ich denke, dass dies eine bewusste Designentscheidung war, die Entwickler dazu zwingen sollte, Funktionen zu erstellen, deren Namen ihre Absichten klar kommunizieren. In C++ würden Entwickler Operatoren mit Funktionen überlasten, die häufig keinen Bezug zu den allgemein akzeptierten Eigenschaften des jeweiligen Operators haben, wodurch es fast unmöglich wird, festzustellen, was ein Codeteil tut, ohne sich die Definition des Operators anzusehen.

6
user14128

Nun, Sie können sich bei Überlastung des Bedieners wirklich in den Fuß schießen. Es ist wie mit Zeigern, die Leute dumme Fehler machen, und so wurde beschlossen, die Schere wegzunehmen.

Zumindest denke ich, dass das der Grund ist ... Ich bin sowieso auf deiner Seite. :)

5
Sarien

Technisch gesehen gibt es in jeder Programmiersprache eine Überladung des Bedieners, die mit verschiedenen Arten von Nummern umgehen kann, z. Ganzzahl und reelle Zahlen. Erläuterung: Der Begriff Überladung bedeutet, dass es für eine Funktion einfach mehrere Implementierungen gibt. In den meisten Programmiersprachen sind verschiedene Implementierungen für den Operator + vorgesehen, eine für ganze Zahlen, eine für reelle. Dies wird als Operatorüberladung bezeichnet.

Nun, viele Leute finden es seltsam, dass Java einen Operator für den Operator + für das Hinzufügen von Strings überlädt, und dies wäre aus mathematischer Sicht zwar merkwürdig, aber vom Standpunkt der Entwickler einer Programmiersprache aus ist es nicht verkehrt, eine eingebaute Operatorüberladung hinzuzufügen für den Operator + für andere Klassen zB String. Die meisten Leute sind sich jedoch einig, dass, sobald Sie die integrierte Überladung für + für String hinzugefügt haben, es in der Regel sinnvoll ist, diese Funktionalität auch für den Entwickler bereitzustellen.

Ein völlig anderer Meinung ist der Irrtum, dass der Operator, der überlastet wird, Code verschleiert, da dies dem Entwickler überlassen bleibt. Das ist naiv zu denken, und um ehrlich zu sein, wird es alt.

+1 zum Hinzufügen von Operatorüberladung in Java 8.

4
Olai

Die Überlastung des Operators führt zu logischen Fehlern des Typs, dass der Operator nicht mit der Operationslogik übereinstimmt. Es ist, als würde er nichts sagen. Der gleiche Fehlertyp tritt auf, wenn der Funktionsname für die Operationslogik ungeeignet ist. Was ist also die Lösung? Dies ist eine komische Antwort - "Unpassend für die Operationslogik", jeder Parametername, jede Klasse, Funktion oder was auch immer logisch ungeeignet sein kann .. Ich denke, dass diese Option in einer respektablen Programmiersprache verfügbar sein sollte, und denjenigen, die denken, dass sie es sind unsicher - hey nein, beide sagen, du musst es benutzen. Nehmen wir das C #. Sie haben die Zeiger heruntergelassen, aber hey - es gibt "unsichere Code" -Anweisungen, die Sie auf eigenes Risiko programmieren.

4
Kvant

Einige Leute sagen, dass die Überladung von Operatoren in Java zu Verwechslungen führen würde. Haben diese Leute jemals aufgehört, sich Java-Code anzusehen, der einige grundlegende Berechnungen durchführt, wie beispielsweise die Erhöhung des finanziellen Werts um einen Prozentsatz mit BigDecimal? .... Die Ausführlichkeit einer solchen Übung wird zur eigenen Demonstration von Obsfuscation. Ironischerweise würden wir durch das Hinzufügen von Operatorüberladung zu Java eine eigene Currency-Klasse erstellen, die einen solchen mathematischen Code elegant und einfach (weniger verwirrt) macht.

3
Volksman

Angenommen, Java als Implementierungssprache, dann wären a, b und c Verweise auf den Typ Complex mit den Anfangswerten null. Angenommen, Complex ist unveränderlich wie das erwähnte BigInteger und ähnliche unveränderliche BigDecimal . Ich denke, Sie meinen das Folgende, da Sie den Verweis auf den Complex zuweisen, der durch das Hinzufügen von b und c zurückgegeben wird. und diese Referenz nicht mit a vergleichen.

Ist nicht:

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

viel einfacher als:

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

Manchmal wäre es schön, einen Operator zu überladen, Freundesklassen und Mehrfachvererbung.

Ich denke jedoch immer noch, dass es eine gute Entscheidung war. Wenn Java eine Überladung der Operatoren hätte, könnten wir niemals die Bedeutung der Operatoren verstehen, ohne den Quellcode zu durchsuchen. Zur Zeit ist das nicht nötig. Und ich denke, Ihr Beispiel für die Verwendung von Methoden anstelle der Überladung von Operatoren ist auch gut lesbar. Wenn Sie die Dinge klarer machen wollen, können Sie immer einen Kommentar über haarigen Aussagen hinzufügen.

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

Alternativen zur nativen Unterstützung von Java Operator Overloading

Da Java keine Operatorüberladung hat, können Sie einige Alternativen prüfen:

  1. Verwenden Sie eine andere Sprache. Beide Groovy und Scala haben eine Operatorüberladung und basieren auf Java.
  2. Verwenden Sie Java-oo , ein Plugin, das das Überladen von Operatoren in Java ermöglicht. Beachten Sie, dass es NICHT plattformunabhängig ist. Außerdem gibt es viele Probleme und ist nicht mit den neuesten Versionen von Java (d. H. Java 10) kompatibel. ( Ursprüngliche StackOverflow-Quelle )
  3. Verwenden Sie JNI , Java Native Interface oder Alternativen. Dadurch können Sie C- oder C++ - Methoden (möglicherweise andere?) Für die Verwendung in Java schreiben. Natürlich ist dies auch NICHT plattformunabhängig.

Wenn jemand von anderen Kenntnis hat, kommentieren Sie ihn bitte, und ich werde ihn dieser Liste hinzufügen.

0
gagarwa

Dies ist kein guter Grund, es nicht zuzulassen, sondern ein praktischer:

Die Leute benutzen es nicht immer verantwortungsvoll. Sehen Sie sich dieses Beispiel aus der Python-Bibliothek an:

>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>> Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

Hier ist die Erklärung:

Der Operator/wurde als Kompositionsoperator zwischen zwei verwendet Schichten. Dabei kann die untere Ebene eine oder mehrere ihrer .__ haben. Standardfelder sind entsprechend der oberen Ebene überladen. (Sie können noch den gewünschten Wert angeben). Ein String kann als Rohschicht verwendet werden.

0
Sarien