Что такое NSObject isEqual: и функция хеша по умолчанию?
У меня есть класс модели базы данных, который является NSObject
. У меня есть набор этих объектов в NSMutableArray
. Я использую indexOfObject:
, чтобы найти совпадение. Проблема заключается в изменении адреса памяти модели объекта. Поэтому я переопределяю метод hash
, чтобы вернуть идентификатор строки модели. Это, однако, не исправляет это. Я также должен переопределить метод isEqual:
для сравнения значения метода hash
.
Что использует метод isEqual:
для определения равенства по умолчанию?
Я предполагаю, что он использует адрес памяти. После чтения документа isEqual:
я думал, что он использовал значение из метода hash
. Очевидно, что это не так, поскольку моя попытка переопределить это значение не решила мою первоначальную проблему.
Ответы
Ответ 1
Как вы правильно догадались, поведение NSObject
default isEqual:
сравнивает адрес памяти объекта. Как ни странно, это не описано в NSObject Class Reference, но оно описано в Introspection, в которой говорится:
Стандартная реализация NSObject
isEqual:
просто проверяет равенство указателя.
Конечно, как вы, несомненно, знаете, подклассы NSObject
могут переопределить isEqual:
, чтобы вести себя по-другому. Например, метод NSString
isEqual:
, когда передается другой NSString
, сначала проверяет адрес, а затем проверяет точное литеральное совпадение между строками.
Ответ 2
Ответ на стандартную реализацию isEqual:
является исчерпывающим. Поэтому я просто добавляю свою заметку о реализации по умолчанию hash
. Вот он:
-(unsigned)hash {return (unsigned)self;}
I. Это только то же значение указателя, которое используется в isEqual:
. Вот как вы можете это проверить:
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@",obj);
NSLog(@"hash: %x",obj.hash);
Результат будет примерно таким:
obj: <NSObject: 0x16d44010>
hash: 16d44010
С наилучшими пожеланиями.
BTW в iOS 8 hash
стал свойством не методом, а там.
Ответ 3
Я бы предположил, что NSObject
isEquals
использует оператор ==
, а hash
использует адрес памяти.
isEquals
метод никогда не должен использовать hash
как абсолютный критерий равенства. Гарантируется наличие двух объектов с аналогичным hashCode
, если вы ищете достаточно объектов (просто создайте более 2 ^ 32 разных объектов, и по крайней мере два из них будут иметь одинаковый hash
).
Другими словами, hash
требует следующую спецификацию: если два объекта равны, то их hash
должен быть равен; однако, если значения двух значений hash
равны, они не обязательно равны.
В качестве подсказки вы всегда должны переопределять isEquals
и hashCode
вместе.