Die kurze Antwort: Konsistenz
Um Ihre Frage jedoch richtig zu beantworten, schlage ich vor, dass wir einen Schritt zurückgehen und uns mit der Frage befassen, was Gleichheit in einer Programmiersprache bedeutet . Es gibt mindestens DREI verschiedene Möglichkeiten, die in verschiedenen Sprachen verwendet werden:
- Referenzgleichheit : bedeutet, dass a = b wahr ist, wenn sich a und b auf dasselbe Objekt beziehen. Es wäre nicht wahr, wenn sich a und b auf verschiedene Objekte beziehen würden, selbst wenn alle Attribute von a und b gleich wären.
- Flache Gleichheit : bedeutet, dass a = b wahr ist, wenn alle Attribute der Objekte, auf die sich a und b beziehen, identisch sind. Flache Gleichheit kann leicht durch einen bitweisen Vergleich des Speicherbereichs implementiert werden, der die beiden Objekte darstellt. Bitte beachten Sie, dass Referenzgleichheit eine geringe Gleichheit impliziert
- Tiefe Gleichheit : bedeutet, dass a = b wahr ist, wenn jedes Attribut in a und b entweder identisch oder tief gleich ist. Bitte beachten Sie, dass eine tiefe Gleichheit sowohl von Referenzgleichheit als auch von flacher Gleichheit impliziert wird. In diesem Sinne ist tiefe Gleichheit die schwächste Form der Gleichheit und Referenzgleichheit die stärkste.
Diese drei Gleichheitstypen werden häufig verwendet, weil sie einfach zu implementieren sind: Alle drei Gleichheitsprüfungen können leicht von einem Compiler generiert werden (im Fall einer tiefen Gleichheit muss der Compiler möglicherweise Tag-Bits verwenden, um Endlosschleifen zu verhindern, wenn eine Struktur dies erfordert) verglichen werden hat zirkuläre Verweise). Es gibt aber noch ein anderes Problem: Keines davon könnte angemessen sein.
In nicht-trivialen Systemen wird Gleichheit von Objekten oft als etwas zwischen tiefer Gleichheit und Referenzgleichheit definiert. Um zu überprüfen, ob wir zwei Objekte in einem bestimmten Kontext als gleich betrachten möchten, müssen möglicherweise einige Attribute mit denen verglichen werden, die sich im Gedächtnis befinden, und andere Attribute müssen mit einer tiefen Gleichheit verglichen werden, während einige Attribute möglicherweise etwas ganz anderes sein dürfen. Was wir wirklich wollen, ist eine „vierte Art von Gleichheit“, eine wirklich schöne, die in der Literatur oft als semantische Gleichheit bezeichnet wird . In unserem Bereich sind die Dinge gleich, wenn sie gleich sind. =)
So können wir auf Ihre Frage zurückkommen:
Gibt es einen großen Vorteil des Standardwerts, den ich einfach vermisse, oder erscheint es vernünftig, dass das Standardverhalten logische Gleichheit ist und standardmäßig auf Referenzgleichheit zurückgegriffen wird, wenn für die Klasse keine logische Gleichheit vorhanden ist?
Was meinen wir, wenn wir 'a == b' in einer beliebigen Sprache schreiben? Im Idealfall sollte es immer dasselbe sein: Semantische Gleichheit. Das ist aber nicht möglich.
Eine der wichtigsten Überlegungen ist, dass wir zumindest für einfache Typen wie Zahlen erwarten, dass zwei Variablen nach der Zuweisung desselben Werts gleich sind. Siehe unten:
var a = 1;
var b = a;
if (a == b){
...
}
a = 3;
b = 3;
if (a == b) {
...
}
In diesem Fall erwarten wir, dass 'a gleich b' in beiden Anweisungen ist. Alles andere wäre verrückt. Die meisten (wenn nicht alle) Sprachen folgen dieser Konvention. Daher wissen wir mit einfachen Typen (auch als Werte bezeichnet), wie man eine semantische Gleichheit erreicht. Bei Objekten kann das etwas ganz anderes sein. Siehe unten:
var a = new Something(1);
var b = a;
if (a == b){
...
}
b = new Something(1);
a.DoSomething();
b.DoSomething();
if (a == b) {
...
}
Wir erwarten, dass das erste "Wenn" immer wahr sein wird. Aber was erwarten Sie beim zweiten "Wenn"? Es kommt wirklich darauf an. Kann 'DoSomething' die (semantische) Gleichheit von a und b verändern?
Das Problem mit der semantischen Gleichheit besteht darin, dass sie vom Compiler nicht automatisch für Objekte generiert werden kann und sich auch nicht aus den Zuweisungen ergibt . Für den Benutzer muss ein Mechanismus bereitgestellt werden, um die semantische Gleichheit zu definieren. In objektorientierten Sprachen ist dieser Mechanismus eine vererbte Methode: equals . Wenn wir einen Teil des OO-Codes lesen, erwarten wir nicht, dass eine Methode in allen Klassen exakt dieselbe Implementierung hat. Wir sind an Vererbung und Überlastung gewöhnt.
Bei Operatoren erwarten wir jedoch dasselbe Verhalten. Wenn Sie 'a == b' sehen, sollten Sie in allen Situationen die gleiche Art von Gleichheit (von den 4 oben) erwarten. Aus Gründen der Konsistenz verwendeten die Sprachdesigner die Referenzgleichheit für alle Typen. Es sollte nicht davon abhängen, ob ein Programmierer eine Methode überschrieben hat oder nicht.
PS: Die Sprache Dee unterscheidet sich geringfügig von Java und C #: Der Gleichheitsoperator bedeutet flache Gleichheit für einfache Typen und semantische Gleichheit für benutzerdefinierte Klassen (wobei die Verantwortung für die Implementierung der = -Operation beim Benutzer liegt - es wird keine Standardeinstellung bereitgestellt). Da für einfache Typen flache Gleichheit immer semantische Gleichheit ist, ist die Sprache konsistent. Der Preis, den es zahlt, ist, dass der Gleichheitsoperator für benutzerdefinierte Typen standardmäßig undefiniert ist. Sie müssen es implementieren. Und manchmal ist das einfach langweilig.