Как вы правильно переопределяете isEqual:
в Objective-C? Кажется, что "улов" состоит в том, что если два объекта равны (как определено методом isEqual:
), они должны иметь одинаковое значение хэширования.
Раздел Introspection в Cocoa Руководство по основам имеет пример того, как переопределить isEqual:
, скопированный следующим образом, для класса с именем MyWidget
:
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToWidget:other];
}
- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
if (self == aWidget)
return YES;
if (![(id)[self name] isEqual:[aWidget name]])
return NO;
if (![[self data] isEqualToData:[aWidget data]])
return NO;
return YES;
}
Он проверяет равенство указателя, затем равенство класса и, наконец, сравнивает объекты с помощью isEqualToWidget:
, который проверяет только свойства name
и data
. Что пример не показывает, как переопределить hash
.
Предположим, что существуют другие свойства, которые не влияют на равенство, скажем age
. Не следует ли переопределить метод hash
таким образом, чтобы на хэш попадали только name
и data
? И если да, как бы вы это сделали? Просто добавьте хэши name
и data
? Например:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Достаточно ли этого? Есть ли лучшая техника? Что делать, если у вас есть примитивы, например int
? Преобразовать их в NSNumber
, чтобы получить их хэш? Или такие структуры, как NSRect
?
( Brain fart: Изначально он писал "побитовое ИЛИ" вместе с |=
. Meant add.)