跳到主要内容

Object-C实现 isEqual 和 hash 方法时要注意什么?

参考答案:

在 Objective-C 中,isEqual:hash 方法通常一起使用,它们对于对象的比较和存储(例如在哈希表中)至关重要。实现这两个方法时,你需要注意以下几点:

isEqual: 方法

  1. 对称性:如果对象 a 与对象 b 相等,那么 b 也应该与 a 相等。即 [a isEqual:b][b isEqual:a] 应该返回相同的结果。

  2. 一致性:只要对象的值在 isEqual: 方法使用的那些属性上没有改变,多次调用 isEqual: 应该返回相同的结果。

  3. 非空性[self isEqual:nil] 应该始终返回 NO

  4. 类型isEqual: 方法应该只在两个对象属于同一类时返回 YES。但是,在某些情况下,你可能希望子类能够与其父类对象比较(例如,一个具体的视图类与其父类视图类)。在这种情况下,你应该在父类中重写 isEqual: 方法,并允许子类进行比较。

  5. 性能isEqual: 方法应该尽可能高效,因为它可能会被频繁调用。

hash 方法

  1. 一致性:如果两个对象根据 isEqual: 方法是相等的,那么它们应该具有相同的哈希值。

  2. 分布:哈希值应该尽量均匀分布,以减少哈希冲突的可能性。

  3. 不变性:只要对象的 isEqual: 方法所依赖的属性没有改变,那么 hash 方法就应该返回相同的结果。

  4. 计算成本hash 方法的计算成本应该相对较低,因为它可能会频繁被调用。

示例

假设你有一个 Person 类,包含 firstNamelastName 两个属性,你可以这样实现 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 类的实例。如果是,它就比较 firstNamelastName 属性。hash 方法则使用 XOR 运算符 ^ 结合 firstNamelastName 的哈希值,以生成一个尽可能均匀的哈希值。