Object-C实现 isEqual 和 hash 方法时要注意什么?
在 Objective-C 中,isEqual:
和 hash
方法通常一起使用,它们对于对象的比较和存储(例如在哈希表中)至关重要。实现这两个方法时,你需要注意以下几点:
isEqual:
方法
-
对称性:如果对象
a
与对象b
相等,那么b
也应该与a
相等。即[a isEqual:b]
和[b isEqual:a]
应该返回相同的结果。 -
一致性:只要对象的值在
isEqual:
方法使用的那些属性上没有改变,多次调用isEqual:
应该返回相同的结果。 -
非空性:
[self isEqual:nil]
应该始终返回NO
。 -
类型:
isEqual:
方法应该只在两个对象属于同一类时返回YES
。但是,在某些情况下,你可能希望子类能够与其父类对象比较(例如,一个具体的视图类与其父类视图类)。在这种情况下,你应该在父类中重写isEqual:
方法,并允许子类进行比较。 -
性能:
isEqual:
方法应该尽可能高效,因为它可能会被频繁调用。
hash
方法
-
一致性:如果两个对象根据
isEqual:
方法是相等的,那么它们应该具有相同的哈希值。 -
分布:哈希值应该尽量均匀分布,以减少哈希冲突的可能性。
-
不变性:只要对象的
isEqual:
方法所依赖的属性没有改变,那么hash
方法就应该返回相同的结果。 -
计算成本:
hash
方法的计算成本应该相对较低,因为它可能会频繁被调用。
示例
假设你有一个 Person
类,包含 firstName
和 lastName
两个属性,你可以这样实现 isEqual:
和 hash
方法:
@interface Person : NSObject
@property (nonatomic, copy) NSString *firstName;
@property (nonatomic, copy) NSString *lastName;
@end
@implementation Person
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if (![object isKindOfClass:[Person class]]) {
return NO;
}
Person *otherPerson = (Person *)object;
return [self.firstName isEqualToString:otherPerson.firstName] &&
[self.lastName isEqualToString:otherPerson.lastName];
}
- (NSUInteger)hash {
return [self.firstName hash] ^ [self.lastName hash];
}
@end
在这个例子中,isEqual:
方法首先检查对象是否是它自己,然后检查对象是否是 Person
类的实例。如果是,它就比较 firstName
和 lastName
属性。hash
方法则使用 XOR 运算符 ^
结合 firstName
和 lastName
的哈希值,以生成一个尽可能均匀的哈希值。