Najlepsze praktyki dla nadrzędnego isEqual: i hash

Jak poprawnie nadpisać isEqual: w Objective-C? "Catch" wygląda na to, że jeśli dwa obiekty są sobie równe( określone metodą isEqual:), muszą mieć tę samą wartość skrótu.

Sekcja introspekcji w Cocoa Fundamentals Guide Zawiera przykład, jak nadpisać isEqual:, skopiowany w następujący sposób dla klasy o nazwie MyWidget:

- (BOOL)isEqual:(id)other {
    if (other == self)
        return YES;
    if (!other || ![other isKindOfClass:[self class]])
        return NO;
    return [self isEqualToWidget:other];
}

- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
    if (self == aWidget)
        return YES;
    if (![(id)[self name] isEqual:[aWidget name]])
        return NO;
    if (![[self data] isEqualToData:[aWidget data]])
        return NO;
    return YES;
}

Sprawdza równość wskaźnika, następnie równość klasy, a na koniec porównuje obiekty za pomocą isEqualToWidget:, które sprawdza tylko właściwości name i data. To, czego przykład nie pokazuje, to sposób nadpisania hash.

Załóżmy, że istnieją inne właściwości, które nie wpływają na równość, powiedzmy age. Czy metoda hash nie powinna być nadpisywana tak, aby tylko name i data wpływały na hash? A jeśli tak, to jak byś to zrobił? Wystarczy dodać hashe name i data? Na przykład:

- (NSUInteger)hash {
    NSUInteger hash = 0;
    hash += [[self name] hash];
    hash += [[self data] hash];
    return hash;
}
Czy to wystarczy? Czy jest lepsza technika? Co jeśli masz prymitywy, jak int? Przekonwertować je na NSNumber, Aby uzyskać ich hash? Czy struktury jak NSRect?

(Brain fart : pierwotnie napisał "bitwise lub" je razem z |=. To znaczy dodać.)

Author: Quinn Taylor, 2008-10-31

17 answers

Zacznij od

 NSUInteger prime = 31;
 NSUInteger result = 1;

Wtedy dla każdego prymitywu, który robisz

 result = prime * result + var

Dla 64bit możesz również chcieć shift i xor.

 result = prime * result + (int) (var ^ (var >>> 32));

Dla obiektów używasz 0 dla nil, a poza tym ich hashcode.

 result = prime * result + [var hash];

Dla booleans używasz dwóch różnych wartości

 result = prime * result + (var)?1231:1237;

Wyjaśnienie i przypisanie

To nie jest praca tcurdta, a komentarze prosiły o więcej wyjaśnień, więc uważam, że edycja dla atrybucji jest sprawiedliwa.

Algorytm ten był spopularyzowana w książce "Effective Java", oraz odpowiedni rozdział można obecnie znaleźć w internecie tutaj . Książka ta spopularyzowała algorytm, który obecnie jest domyślnie stosowany w wielu aplikacjach Java (w tym w Eclipse). Wywodzi się jednak z jeszcze starszej implementacji, która jest różnie przypisywana Danowi Bernsteinowi lub Chrisowi Torekowi. Ten starszy algorytm pierwotnie krążył po Usenecie i pewne przypisanie jest trudne. Na przykład, istnieje kilka interesujące komentarz w tym kodzie Apache (szukaj ich nazw), który odwołuje się do oryginalnego źródła.

Podsumowując, jest to bardzo stary, prosty algorytm hashujący. Nie jest najbardziej wydajny, a nawet nie udowodniono matematycznie, że jest "dobrym" algorytmem. Ale jest to proste i wiele osób używało go przez długi czas z dobrymi wynikami, więc ma wiele historycznego wsparcia.

 110
Author: tcurdt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 09:10:33

Sam odbieram Objective-C, więc nie mogę mówić konkretnie w tym języku, ale w innych językach, których używam, Jeśli dwie instancje są "równe", muszą zwracać ten sam hash - w przeciwnym razie będziesz miał różnego rodzaju problemy, próbując użyć ich jako kluczy w hashtable (lub dowolnych kolekcjach słownikowych).

Z drugiej strony, jeśli 2 instancje nie są sobie równe, mogą lub nie muszą mieć ten sam hash - najlepiej, jeśli nie. to jest różnica między O(1) wyszukiwanie w tabeli hash I O (N) - jeśli wszystkie hasze się zderzą, może się okazać, że wyszukiwanie w tabeli nie jest lepsze niż wyszukiwanie na liście.

Jeśli chodzi o najlepsze praktyki, Twój hash powinien zwracać losowy rozkład wartości dla swoich danych wejściowych. Oznacza to, że na przykład, jeśli masz podwójną wartość, ale większość wartości ma tendencję do klastra między 0 a 100, musisz upewnić się, że skróty zwracane przez te wartości są równomiernie rozłożone w całym możliwym zakresie wartości hash. To znacznie poprawi Twoją wydajność.

Istnieje wiele algorytmów haszujących, w tym kilka wymienionych tutaj. Staram się unikać tworzenia nowych algorytmów skrótu, ponieważ może to mieć duże implikacje wydajności, więc używanie istniejących metod skrótu i wykonywanie bitowej kombinacji jakiegoś rodzaju, jak to robisz w swoim przykładzie, jest dobrym sposobem na uniknięcie tego.

 81
Author: Brian B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 18:27:13

Uznałem ten wątek za niezwykle pomocny, dostarczając wszystko, czego potrzebowałem, aby moje metody isEqual: i hash zostały zaimplementowane za pomocą jednego haczyka. Podczas testowania zmiennych instancji obiektu w isEqual: przykładowy kod używa:

if (![(id)[self name] isEqual:[aWidget name]])
    return NO;

To wielokrotnie nie powiodło się ( tj., zwróciło Nie ) Bez i błąd, gdy wiedział obiekty były identyczne w moich testach jednostkowych. Powodem było to, że jedną ze zmiennych instancji NSString było nil Tak więc powyższe stwierdzenie było:

if (![nil isEqual: nil])
    return NO;

A ponieważ nil odpowie na każdą metodę, jest to całkowicie legalne, ale

[nil isEqual: nil]

Zwraca nil , co oznacza NO , więc jeśli zarówno badany obiekt, jak i badany obiekt miał nil , będą one uważane za nie równe (, tj., isEqual: zwróci Nie ).

Ta prosta poprawka polegała na zmianie instrukcji if na:

if ([self name] != [aWidget name] && ![(id)[self name] isEqual:[aWidget name]])
    return NO;

W ten sposób, jeśli ich adresy są takie same, pomija wywołanie metody no Materia, jeśli oba są nil lub oba wskazują na ten sam obiekt, ale jeśli albo nie jest nil lub wskazują na różne obiekty, to odpowiednio nazywa się komparator.

Mam nadzieję, że oszczędzi to komuś kilku minut drapania się po głowie.
 27
Author: LavaSlider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-26 19:21:01

Wystarczy prosty XOR nad wartościami hash krytycznych właściwości W 99% przypadków.

Na przykład:

- (NSUInteger)hash
{
    return [self.name hash] ^ [self.data hash];
}

Rozwiązanie Znalezione w http://nshipster.com/equality / By Mattt Thompson (który również odniósł się do tego pytania w swoim poście!)

 27
Author: Yariv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-28 20:00:57

Funkcja skrótu powinna utworzyć pół-unikalną wartość, która prawdopodobnie nie zderzy się lub nie dopasuje wartości skrótu innego obiektu.

Oto pełna funkcja hash, która może być dostosowana do zmiennych instancji klas. Używa NSUInteger zamiast int dla kompatybilności w aplikacjach 64 / 32bit.

Jeśli wynik będzie równy 0 dla różnych obiektów, istnieje ryzyko kolizji skrótów. Kolizja hashów może spowodować nieoczekiwane zachowanie programu podczas pracy z niektórymi z klasy kolekcji, które zależą od funkcji hash. Przed użyciem upewnij się, że przetestowałeś swoją funkcję skrótu.

-(NSUInteger)hash {
    NSUInteger result = 1;
    NSUInteger prime = 31;
    NSUInteger yesPrime = 1231;
    NSUInteger noPrime = 1237;

    // Add any object that already has a hash function (NSString)
    result = prime * result + [self.myObject hash];

    // Add primitive variables (int)
    result = prime * result + self.primitiveVariable; 

    // Boolean values (BOOL)
    result = prime * result + self.isSelected?yesPrime:noPrime;

    return result;
}
 20
Author: Paul Solt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-24 21:40:01

To bardzo mi pomogło! To może być odpowiedź, której szukasz. implementowanie równości i hashowania

 18
Author: Steve M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 06:21:15

Łatwym, ale nieefektywnym sposobem jest zwrócenie tej samej wartości -hash dla każdej instancji. W przeciwnym razie, tak, musisz zaimplementować hash tylko w oparciu o obiekty, które wpływają na równość. Jest to trudne, jeśli używasz porównań typu lax w -isEqual: (np. porównania łańcuchów bez rozróżniania wielkości liter). W przypadku ints, możesz ogólnie używać samego int, chyba że porównasz z NSNumbers.

Nie używaj/=, ale nasyci się. Zamiast tego użyj^=.

Losowe ciekawostki: [[NSNumber numberWithInt:0] isEqual:[NSNumber numberWithBool:NO]], ale [[NSNumber numberWithInt:0] hash] != [[NSNumber numberWithBool:NO] hash]. (rdar: / / 4538282, otwarte od 05-May-2006)

 13
Author: Jens Ayton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 17:34:06

Pamiętaj, że musisz tylko podać hash, który jest równy, gdy isEqual jest prawdą. Gdy isEqual jest false, hash nie musi być nierówny, choć prawdopodobnie tak jest. Stąd:

Trzymaj hash prosty. Wybierz zmienną członka (lub kilka członków), która jest najbardziej charakterystyczna.

Na przykład dla CLPlacemark wystarczy tylko nazwa. Tak są 2 lub 3 odróżnienia CLPlacemark o dokładnie tej samej nazwie, ale te są rzadkie. Użyj tego haszu.

@interface CLPlacemark (equal)
- (BOOL)isEqual:(CLPlacemark*)other;
@end

@implementation CLPlacemark (equal)

...

-(NSUInteger) hash
{
    return self.name.hash;
}


@end

Zawiadomienie Nie zawracam sobie głowy określaniem miasta, kraju itp. Imię wystarczy. Może imię i nazwisko.

Hash powinien być równomiernie rozłożony. Możesz więc połączyć kilka zmiennych składowych używając znaku caret ^ (XOR)

Więc to coś w stylu

hash = self.member1.hash ^ self.member2.hash ^ self.member3.hash

W ten sposób hash będzie równomiernie rozłożony.

Hash must be O(1), and not O(n)

Więc co robić w tablicy?

Znowu proste. Nie musisz hashować wszystkich członków tablicy. Wystarczy hashować pierwszy element, ostatni element, licznik, może jakieś środkowe elementy i tyle.
 10
Author: user4951,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-24 01:40:30

Trzymaj się, z pewnością o wiele łatwiejszym sposobem na to jest najpierw nadpisanie - (NSString )description i dostarczenie ciągowej reprezentacji stanu obiektu(musisz reprezentować cały stan obiektu w tym łańcuchu).

Następnie podaj następującą implementację hash:

- (NSUInteger)hash {
    return [[self description] hash];
}

Opiera się to na zasadzie, że "jeżeli dwa obiekty łańcuchowe są sobie równe (określone metodą isEqualToString:), to muszą mieć tę samą wartość skrótu."

Źródło: Klasa NSString Odniesienie

 7
Author: Jonathan Ellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-17 21:48:58

Kontrakty equals i hash są dobrze sprecyzowane i dokładnie zbadane w świecie Javy (zobacz odpowiedź @mipardi), ale wszystkie te same względy powinny mieć zastosowanie do Objective-C. {25]} Eclipse wykonuje niezawodne zadanie generowania tych metod w Javie, więc oto przykład Eclipse przeniesiony ręcznie do Objective-C:]}

- (BOOL)isEqual:(id)object {
    if (self == object)
        return true;
    if ([self class] != [object class])
        return false;
    MyWidget *other = (MyWidget *)object;
    if (_name == nil) {
        if (other->_name != nil)
            return false;
    }
    else if (![_name isEqual:other->_name])
        return false;
    if (_data == nil) {
        if (other->_data != nil)
            return false;
    }
    else if (![_data isEqual:other->_data])
        return false;
    return true;
}

- (NSUInteger)hash {
    const NSUInteger prime = 31;
    NSUInteger result = 1;
    result = prime * result + [_name hash];
    result = prime * result + [_data hash];
    return result;
}

I dla podklasy YourWidget, która dodaje Właściwość serialNo:

- (BOOL)isEqual:(id)object {
    if (self == object)
        return true;
    if (![super isEqual:object])
        return false;
    if ([self class] != [object class])
        return false;
    YourWidget *other = (YourWidget *)object;
    if (_serialNo == nil) {
        if (other->_serialNo != nil)
            return false;
    }
    else if (![_serialNo isEqual:other->_serialNo])
        return false;
    return true;
}

- (NSUInteger)hash {
    const NSUInteger prime = 31;
    NSUInteger result = [super hash];
    result = prime * result + [_serialNo hash];
    return result;
}

Ta implementacja pozwala uniknąć pewnych pułapek podklasowania w próbce isEqual: z Jabłko:

  • Test klasy Apple other isKindOfClass:[self class] jest asymetryczny dla dwóch różnych podklas MyWidget. Równość musi być symetryczna: a = b wtedy i tylko wtedy, gdy b = a. można to łatwo naprawić zmieniając test na other isKindOfClass:[MyWidget class] , wtedy wszystkie MyWidget podklasy będą wzajemnie porównywalne.
  • użycie testu isKindOfClass: podklasy zapobiega nadpisywaniu isEqual: wyrafinowanym testem równości. Jest tak, ponieważ równość musi być przechodnia: jeśli A=b I a=c, to b = c. jeśli instancja MyWidget porównuje równe do dwóch instancji YourWidget, wtedy te YourWidget muszą być równe sobie, nawet jeśli ich serialNo różnią się.

Druga sprawa może zostać rozwiązana przez rozważenie obiektów jako równe tylko wtedy, gdy należą do tej samej klasy, stąd test [self class] != [object class] tutaj. Dla typowych klas aplikacji wydaje się to być najlepszym podejściem.

Jednak z pewnością są przypadki, w których test isKindOfClass: jest preferowany. Jest to bardziej typowe dla klas framework niż klasy aplikacji. Na przykład każdy NSString powinien być porównywany z każdym innym NSString z tym samym sekwencją znaków, niezależnie od NSString/NSMutableString rozróżnienie, a także niezależnie od tego, jakie klasy prywatne w klastrze klas NSString są zaangażowane.

W takich przypadkach, isEqual: powinny mieć dobrze zdefiniowane, dobrze udokumentowane zachowanie i powinno być jasne, że podklasy nie mogą tego zastąpić. W języku Java ograniczenie "no override" może być wymuszone przez oznaczanie równych i metody hashcode jako final, Ale Objective-C nie ma odpowiednika.

 5
Author: jedwidz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-19 10:32:42

To nie odpowiada bezpośrednio na twoje pytanie (w ogóle), ale wcześniej używałem MurmurHash do generowania hashów: murmurhash

Chyba powinienem wyjaśnić dlaczego: szmer jest cholernie szybki...

 5
Author: schwa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 06:21:57

Znalazłem ta strona jako pomocny przewodnik w metodach override equals i hash. Zawiera przyzwoity algorytm obliczania kodów skrótu. Strona jest nastawiona na Javę, ale dość łatwo jest dostosować ją do Objective-C / Cocoa.

 5
Author: mipadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-04 19:00:36

Też jestem nowicjuszem Objective C, ale znalazłem doskonały artykuł o tożsamości a równość w Objective C tutaj . Z mojego czytania wynika, że być może będziesz w stanie zachować domyślną funkcję hash (która powinna zapewnić unikalną tożsamość) i zaimplementować metodę isEqual, aby porównywała wartości danych.

 4
Author: ceperry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-24 15:04:49

Quinn się myli, że odniesienie do szmeru jest tutaj bezużyteczne. Quinn ma rację, że chcesz zrozumieć teorię haszowania. Szmery w dużej mierze przekładają tę teorię na implementację. Warto dowiedzieć się, jak zastosować tę implementację do tej konkretnej aplikacji.

Niektóre z kluczowych punktów tutaj:

Przykładowa funkcja z tcurdt sugeruje, że '31' jest dobrym mnożnikiem, ponieważ jest liczbą pierwszą. Trzeba pokazać, że bycie pierwszorzędnym jest warunkiem koniecznym i wystarczającym. W rzeczywistości 31 (i 7) prawdopodobnie nie są szczególnie dobrymi liczbami pierwszymi, ponieważ 31 == -1% 32. Nieparzysty mnożnik z około połową bitów ustawionych i połową bitów czystych prawdopodobnie będzie lepszy. (Stała mnożenia szmeru ma tę właściwość.)

Ten typ funkcji skrótu byłby prawdopodobnie silniejszy, gdyby po pomnożeniu wartość wyniku została skorygowana za pomocą przesunięcia i xor. Mnożenie ma tendencję do uzyskiwania wyników wielu oddziaływań bitowych na wysokim końcu rejestru i niskie wyniki interakcji na dolnym końcu rejestru. Shift i xor zwiększają interakcje na dolnym końcu rejestru.

Ustawienie początkowego wyniku na wartość, gdzie około połowa bitów to zero, a około połowa to jeden, również byłoby przydatne.

Warto uważać na kolejność łączenia elementów. Należy prawdopodobnie najpierw przetworzyć booleany i inne elementy, w których wartości są nie jest silnie rozproszony.

Przydatne może być dodanie kilku dodatkowych etapów kodowania bitów na końcu obliczeń.

Czy szmer hash jest rzeczywiście szybki dla tej aplikacji jest otwarte pytanie. Hash szmeru premiuje bity każdego słowa wejściowego. Wiele słów wejściowych może być przetwarzanych równolegle, co pomaga procesorom o wielu problemach.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-31 19:02:29

Łącząc odpowiedź @tcurdt z odpowiedzią @ oscar-gomez za uzyskanie nazw właściwości , możemy stworzyć łatwe rozwiązanie zarówno dla isEqual, jak i hash:

NSArray *PropertyNamesFromObject(id object)
{
    unsigned int propertyCount = 0;
    objc_property_t * properties = class_copyPropertyList([object class], &propertyCount);
    NSMutableArray *propertyNames = [NSMutableArray arrayWithCapacity:propertyCount];

    for (unsigned int i = 0; i < propertyCount; ++i) {
        objc_property_t property = properties[i];
        const char * name = property_getName(property);
        NSString *propertyName = [NSString stringWithUTF8String:name];
        [propertyNames addObject:propertyName];
    }
    free(properties);
    return propertyNames;
}

BOOL IsEqualObjects(id object1, id object2)
{
    if (object1 == object2)
        return YES;
    if (!object1 || ![object2 isKindOfClass:[object1 class]])
        return NO;

    NSArray *propertyNames = PropertyNamesFromObject(object1);
    for (NSString *propertyName in propertyNames) {
        if (([object1 valueForKey:propertyName] != [object2 valueForKey:propertyName])
            && (![[object1 valueForKey:propertyName] isEqual:[object2 valueForKey:propertyName]])) return NO;
    }

    return YES;
}

NSUInteger MagicHash(id object)
{
    NSUInteger prime = 31;
    NSUInteger result = 1;

    NSArray *propertyNames = PropertyNamesFromObject(object);

    for (NSString *propertyName in propertyNames) {
        id value = [object valueForKey:propertyName];
        result = prime * result + [value hash];
    }

    return result;
}

Teraz w swojej klasie niestandardowej możesz łatwo zaimplementować isEqual: i hash:

- (NSUInteger)hash
{
    return MagicHash(self);
}

- (BOOL)isEqual:(id)other
{
    return IsEqualObjects(self, other);
}
 3
Author: johnboiles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:12

Zauważ, że jeśli tworzysz obiekt, który może zostać zmutowany po utworzeniu, wartość hash musi nie zmieniać jeśli obiekt zostanie wstawiony do kolekcji. W praktyce oznacza to, że wartość hash musi być ustalona od punktu początkowego utworzenia obiektu. Zobacz dokumentację Apple na temat metody hash protokołu NSObject Aby uzyskać więcej informacji:

Jeśli zmienny obiekt jest dodawany do kolekcji, która używa wartości skrótu do określenia pozycja w kolekcji, wartość zwracana metodą hash obiektu nie może się zmieniać, gdy obiekt znajduje się w kolekcji. W związku z tym metoda hash nie może polegać na żadnych wewnętrznych informacjach o stanie obiektu lub Należy upewnić się, że wewnętrzne informacje o stanie obiektu Nie ulegną zmianie, gdy obiekt znajduje się w kolekcji. Tak więc, na przykład, zmienny słownik można umieścić w tabeli hash, ale nie wolno go zmieniać, gdy jest tam. (Zauważ, że może to być trudne wiedzieć, czy dany obiekt znajduje się w zbiorze.)

Dla mnie to brzmi jak kompletne szaleństwo, ponieważ potencjalnie skutecznie sprawia, że wyszukiwanie hashów jest znacznie mniej wydajne, ale przypuszczam, że lepiej jest błądzić po stronie ostrożności i podążać za tym, co mówi dokumentacja.

 2
Author: user10345,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-03 01:05:42

Przepraszam, jeśli zaryzykowałem, że brzmię tu kompletnym idiotą, ale... ...nikt nie zadał sobie trudu wspomnieć, że aby stosować się do "najlepszych praktyk", zdecydowanie nie należy określać metody equals, która nie uwzględniałaby wszystkich danych należących do obiektu docelowego, np. jakiekolwiek dane są agregowane z Twoim obiektem, a powiązane z nim, powinny być brane pod uwagę przy implementacji equals. Jeśli nie chcesz brać pod uwagę, powiedzmy "wiek" w porównaniu, to powinieneś napisać komparator i użyć go do wykonaj swoje porównania zamiast isEqual:.

Jeśli zdefiniujesz metodę isEqual:, która wykonuje arbitralnie porównanie równości, ryzykujesz, że ta metoda zostanie niewłaściwie użyta przez innego programistę, lub nawet siebie, gdy zapomnisz o 'twist' w Twojej interpretacji równości.

Ergo, chociaż jest to świetne pytanie na temat haszowania, zwykle nie musisz redefiniować metody haszowania, powinieneś raczej zdefiniować komparator ad-hoc.

 1
Author: Thibaud de Souza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-05 16:40:55