Что такое NSObject isEqual: и хэш-функция по умолчанию? - PullRequest
27 голосов
/ 07 августа 2009

У меня есть класс модели базы данных, NSObject. У меня есть набор этих объектов в NSMutableArray. Я использую indexOfObject:, чтобы найти совпадение. Проблема заключается в изменении адреса памяти объекта модели. Поэтому я переопределяю метод hash, чтобы вернуть идентификатор строки модели. Это однако не исправляет это. Я также должен переопределить метод isEqual:, чтобы сравнить значение метода hash.

Что метод isEqual: использует для определения равенства по умолчанию?

Я предполагаю, что он использует адрес памяти. После прочтения документации isEqual: я подумал, что она использует значение из метода hash. Очевидно, что это не так, поскольку моя попытка переопределить это значение не решила мою первоначальную проблему.

Ответы [ 3 ]

28 голосов
/ 23 ноября 2010

Как вы правильно догадались, поведение isEqual: по умолчанию NSObject сравнивает адрес памяти объекта. Как ни странно, в настоящее время это не задокументировано в Ссылка на класс NSObject , но задокументировано в Introspection документации, в которой говорится:

Стандартная NSObject реализация isEqual: просто проверяет равенство указателей.

Конечно, как вы, несомненно, знаете, подклассы NSObject могут переопределить isEqual:, чтобы вести себя по-другому. Например, метод NSString isEqual: при передаче другого NSString сначала проверяет адрес, а затем проверяет точное литеральное совпадение между строками.

9 голосов
/ 01 октября 2014

Ответ о реализации по умолчанию isEqual: является исчерпывающим. Поэтому я просто добавляю заметку о реализации по умолчанию hash. Вот оно:

-(unsigned)hash {return (unsigned)self;}

Т.е. это то же самое значение указателя, которое используется в isEqual:. Вот как это можно проверить:

NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@",obj);
NSLog(@"hash: %x",obj.hash);

Результат будет примерно таким:

obj: <NSObject: 0x16d44010>
hash: 16d44010

С наилучшими пожеланиями.

Кстати, в iOS 8 hash стало свойством, а не методом, но оно есть.

4 голосов
/ 07 августа 2009

Я бы предположил, что NSObject isEquals использует оператор ==, а hash использует адрес памяти.

isEquals метод никогда не должен использовать hash в качестве абсолютного теста на равенство. Гарантируется наличие двух объектов с одинаковым hashCode, если вы ищете достаточно объектов (просто создайте более 2 ^ 32 разных объектов, и по крайней мере два из них будут иметь одинаковые hash).

Другими словами, hash требует следующей спецификации: если два объекта равны, то их hash должно быть равным; однако, если значения hash двух объектов равны, они не обязательно равны.

Как подсказка, вы всегда должны переопределять isEquals и hashCode вместе.

...