08@理解“对象等同性”这一概念

300 阅读2分钟
  • 若想检测对象的等同性,请提供isEqual:hash方法
  • 相同的对象必须具有相同的哈希码,但是两个哈希码相同的对象却未必相同
  • 不要盲目的逐个检测每条属性,而是应该依据具体需求来指定检查方案。
  • 编写hash方法时,应该使用计算速度快而且哈希码碰撞几率低的算法。

1、isEqual方法与==区别

NSString *foo = @"Badger 123";
NSString *bar = [NSStringstringWithFormat:@"Badger %i", 123];
BOOL eaualA = (foo == bar); // NO
BOOL equalB = [foo isEqual: bar]; // YES
BOOL equalC = [foo isEqualToString: bar]; // YES

区别:

  • ==比较的是两个对象的指针本身,而不是其所指的对象。
  • NSObject协议中声明isEqual来判断对象等同性
  • 某些特殊对象提供了特殊的“等同性判定方法”。例如isEqualToString,推荐使用此方法。

2、isEqualhash方法

-(BOOL)isEqual:(id)object;
-(NSUInterger)hash;

NSObject对象中这两个方法的默认实现是:当且仅当“指针值”相等时,这两个对象才相等。

EOCPerson类的自定义覆写

-(BOOL)isEqual:(id)object {
    // 1、检查指针是否相等
    if (self == object) return YES;
    // 2、判断类型是否相等
    if ([self class] != [object class]) return NO;
    
    // 3、判断属性是否相等
    EOCPerson *otherPerson = (EOCPerson *)object
    ......
    
    return YES;
}

/// 推荐hash方法的写法. YYAsyncLayer也是这种写法。
-(NSUInteger)hash {
    NSUInteger firlstNameHash = [_firstName hash];
    NSUInteger lastNameHash = [_lastName hash];
    NSUnteger ageHash = _age;
    return firstNameHash ^ lastNameHash ^ ageHash;
}

3、特定类具有等同性判定方法

无需检测参数类型,代码如下

// 覆写isEqual方法
-(BOOL)isEqual:(id)object{
    if ([self class] == [object class]) {
        return [self isEqualToPerson:(EOCPerson*)object];
    }else {
        return [super isEqual: object]
    }
}
-(BOOL)isEqualToPerson:(EOCPerson*)otherPerson {
    if (self == object) return YES;
    if (![_firstName isEqualToString:otherPerson.firstName]) {
        return NO;
    }
    ... 其他属性判断
    return YES;
}

4、等同性判定的执行深度

NSArray的深度等同性判定,特定类的主键字段判定。

5、容器中可变类的等同性

某个对象放入collection之后就不应该在改变哈希码。collection会把各个对象按照其哈希码分装到不同的“箱子数组”中。