Что такое NSObject isEqual:и хеш-функция по умолчанию?
-
12-09-2019 - |
Вопрос
У меня есть класс модели базы данных, который представляет собой NSObject
.У меня есть набор этих объектов в NSMutableArray
.я использую indexOfObject:
чтобы найти совпадение.Проблема заключается в изменении адреса памяти объекта модели.Поэтому я переопределяю hash
метод для возврата идентификатора строки модели.Однако это не исправляет ситуацию.Мне также нужно переопределить isEqual:
метод сравнения стоимости hash
метод.
Что это isEqual:
использовать метод для определения равенства по умолчанию?
Я предполагаю, что он использует адрес памяти.После прочтения isEqual:
документации, я думал, что она использовала значение из hash
метод.Очевидно, что это не так, поскольку моя попытка переопределить это значение не решила мою первоначальную проблему.
Решение
Как вы правильно догадались, 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
стал свойством, а не методом, но он есть.
Я бы предположил, что NSObject
isEquals
использует ==
оператор и hash
использует адрес памяти.
isEquals
метод никогда не должен использовать hash
как абсолютный критерий равенства.Гарантировано наличие двух объектов, имеющих одинаковые значения. hashCode
, если вы ищете достаточно объектов (просто создайте более 2^32 разных объектов, и как минимум два из них будут иметь одинаковые hash
).
Другими словами, hash
требуется следующая спецификация:Если два объекта равны, то их hash
должен быть равным;однако, если два объекта hash
значения равны, они не обязательно равны.
Совет: всегда следует переопределять isEquals
и hashCode
вместе.