Krótka odpowiedź: spójność
Aby jednak odpowiedzieć na twoje pytanie, proponuję zrobić krok do tyłu i przyjrzeć się temu, co oznacza równość w języku programowania. Istnieją co najmniej TRZY różne możliwości, które są używane w różnych językach:
- Równość odniesienia : oznacza, że a = b jest prawdziwe, jeśli aib odnoszą się do tego samego obiektu. Nie byłoby prawdą, gdyby aib odnosiły się do różnych obiektów, nawet gdyby wszystkie atrybuty aib były takie same.
- Płytka równość : oznacza, że a = b jest prawdziwe, jeśli wszystkie atrybuty obiektów, do których odnoszą się a i b, są identyczne. Płytką równość można łatwo wdrożyć przez bitowe porównanie przestrzeni pamięci reprezentującej dwa obiekty. Należy pamiętać, że równość odniesienia oznacza płytką równość
- Głęboka równość : oznacza, że a = b jest prawdą, jeśli każdy atrybut aib jest albo identyczny albo głęboko równy. Należy pamiętać, że głęboka równość jest implikowana zarówno przez równość odniesienia, jak i równość płytką. W tym sensie głęboka równość jest najsłabszą formą równości, a równość odniesienia jest najsilniejsza.
Te trzy typy równości są często używane, ponieważ są wygodne do wdrożenia: wszystkie trzy kontrole równości mogą być łatwo wygenerowane przez kompilator (w przypadku głębokiej równości kompilator może wymagać użycia bitów znaczników, aby zapobiec nieskończonym pętlom, jeśli struktura do porównania ma odniesienia cykliczne). Istnieje jednak inny problem: żaden z nich może nie być odpowiedni.
W systemach nietrywialnych równość obiektów jest często definiowana jako coś pomiędzy równością głęboką a równością odniesienia. Aby sprawdzić, czy chcemy uznać dwa obiekty za równe w pewnym kontekście, możemy wymagać porównania niektórych atrybutów z tym, gdzie stoi w pamięci, a innych głębokiej równości, podczas gdy niektóre atrybuty mogą być czymś zupełnie innym. To, co naprawdę chcielibyśmy, to „czwarty typ równości”, naprawdę miły, często nazywany w literaturze równością semantyczną . Rzeczy są równe, jeśli są równe, w naszej domenie. =)
Możemy więc wrócić do twojego pytania:
Czy jest jakaś istotna korzyść z niewywiązania się z tego, czego mi po prostu brakuje, czy też wydaje się uzasadnione, że domyślnym zachowaniem powinna być logiczna równość, i powrót do równości referencyjnej, jeśli nie istnieje logiczna równość dla klasy?
Co mamy na myśli, gdy piszemy „a == b” w dowolnym języku? Idealnie powinno być zawsze tak samo: równość semantyczna. Ale to nie jest możliwe.
Jednym z głównych założeń jest to, że przynajmniej dla prostych typów, takich jak liczby, oczekujemy, że dwie zmienne są równe po przypisaniu tej samej wartości. Patrz poniżej:
var a = 1;
var b = a;
if (a == b){
...
}
a = 3;
b = 3;
if (a == b) {
...
}
W tym przypadku oczekujemy, że „a jest równe b” w obu instrukcjach. Wszystko inne byłoby szalone. Większość (jeśli nie wszystkie) języków jest zgodna z tą konwencją. Dlatego dzięki prostym typom (czyli wartościom) wiemy, jak osiągnąć równość semantyczną. W przypadku obiektów może to być coś zupełnie innego. Patrz poniżej:
var a = new Something(1);
var b = a;
if (a == b){
...
}
b = new Something(1);
a.DoSomething();
b.DoSomething();
if (a == b) {
...
}
Oczekujemy, że pierwsze „jeśli” zawsze będzie prawdziwe. Ale czego oczekujesz od drugiego „jeśli”? To naprawdę zależy. Czy „DoSomething” może zmienić (semantyczną) równość aib?
Problem z równością semantyczną polega na tym, że kompilator nie może automatycznie wygenerować obiektów, ani nie wynika to z przypisań . Użytkownik musi zapewnić mechanizm definiowania równości semantycznej. W językach obiektowych mechanizm ten jest dziedziczoną metodą: równa się . Czytając fragment kodu OO, nie oczekujemy, że metoda będzie miała taką samą dokładną implementację we wszystkich klasach. Jesteśmy przyzwyczajeni do dziedziczenia i przeciążania.
Jednak w przypadku operatorów oczekujemy tego samego zachowania. Kiedy zobaczysz „a == b”, powinieneś spodziewać się tego samego rodzaju równości (od 4 powyżej) we wszystkich sytuacjach. Tak więc, dążąc do spójności , projektanci języków stosowali równość odniesienia dla wszystkich typów. Nie powinno to zależeć od tego, czy programista zastąpił metodę, czy nie.
PS: Język Dee jest nieco inny niż Java i C #: operator równości oznacza płytką równość dla prostych typów i równość semantyczną dla klas zdefiniowanych przez użytkownika (z odpowiedzialnością za wdrożenie operacji = leżącej po stronie użytkownika - nie podano domyślnej). Ponieważ w przypadku prostych typów płytka równość jest zawsze równością semantyczną, język jest spójny. Cena, którą płaci, polega jednak na tym, że operator równości jest domyślnie niezdefiniowany dla typów zdefiniowanych przez użytkownika. Musisz to zaimplementować. A czasem jest to po prostu nudne.