Что такое 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
стало свойством, а не методом, но оно есть.
Я бы предположил, что NSObject
isEquals
использует ==
оператор и hash
использует адрес памяти.
isEquals
метод никогда не должен использовать hash
в качестве абсолютного теста на равенство. Гарантируется наличие двух одинаковых объектов hashCode
, если вы ищете достаточно объектов (просто создайте более 2^32 различных объектов, и по крайней мере два из них будут иметь одинаковые hash
).
Другими словами, hash
требуется следующая спецификация: если два объекта равны, то их hash
должен быть равным; Однако, если два объекта hash
значения равны, они не обязательно равны.
Как совет, вы всегда должны переопределить isEquals
а также hashCode
все вместе.