Что такое NSObject isEqual: и хэш-функция по умолчанию?

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

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

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

3 ответа

Решение

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

По умолчанию NSObject реализация isEqual: просто проверяет равенство указателей.

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

Ответ о дефолтной реализации 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 стало свойством, а не методом, но оно есть.

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

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

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

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

Другие вопросы по тегам