美文网首页
第 8 条:理解“对象等同性”这一概念

第 8 条:理解“对象等同性”这一概念

作者: 对歌当酒 | 来源:发表于2016-01-08 14:53 被阅读62次

    == 操作符比较的是两个指针本身,而不是其所指的对象。应使用 NSObject 协议中声明的 isEqual: 方法来判断两个对象的等同性。

    例如:

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

    NSObject 协议中有两个判断等同性的关键方法:

    - (BOOL)isEqual:(id)object;
    + (NSUInteger)hash;
    // 这两个方法的默认实现是:当且仅当其“指针值”(pointer value)完全相等时,两个对象才相等。
    

    注意:若 isEqual: 方法判定两个对象相等,那么其 hash 方法也必须返回同一个值;若两个对象的 hash 方法返回同一个值,那么 isEqual: 未必认为二者相等。

    hash: 方法实现

    /* 方法一 */
    - (NSUInteger)hash {
        return 1337;
    }
    
    /* 方法二 */
    - (NSUInteger)hash {
        NSString *stringToHash = [NSString stringWithFormat:@"%@:%@", _firstName, _lastName];
        return [stringToHash hash];
    }
    
    /* 方法三 */
    - (NSUInteger)hash {
        NSUInteger firstNameHash = [_firstName hash];
        NSUInteger lastNameHash = [_lastName hash];
        return firstNameHash ^ lastNameHash; //按位异或
    }
    

    三种方法对比:
    方法一:会产生性能问题。
    方法二:创建字符串开销,添加到collection也会有性能问题。
    方法三:高效,哈希码在一定范围内,会碰撞。

    特定类的等同性判断方法

    NSString: isEqualToString:
    NSArray: isEqualToArray:
    NSDictionary: isEqualToDictionary:

    自定义判断等同性方法:

    - (BOOL)isEqualToPerson:(ViewController*)otherPerson {
        if (self == otherPerson) return YES;
        
        if (![_firstName isEqualToString:otherPerson.firstName]) {
            return NO;
        }
        if (![_lastName isEqualToString:otherPerson.lastName]) {
            return NO;
        }
        return YES;
    }
    
    // 重写“isEqual:”方法
    - (BOOL)isEqual:(id)object {
        if ([self class] == [object class]) {
            return [self isEqualToPerson:(ViewController*)object];
        } else {
            return [super isEqual:object];
        }
    }
    

    等同性判定执行深度

    有时无需将所有数据逐个比较,只根据其中一部分数据即可判断二者是否等同。

    容器中可变类的等同性

    把某个对象放入 collection 之后,就不应再改变其哈希码了。

    要点:

    • 相同的对象必须有相同的哈希码,但哈希码相同的对象未必相同。
    • 不要盲目地逐个检测每条属性,应依照具体需求来检测。
    • 编写 hash 方法时,应使用计算速度快且哈希码碰撞几率低的算法。

    主要来源:《Effective Objective-C 2.0》

    相关文章

      网友评论

          本文标题:第 8 条:理解“对象等同性”这一概念

          本文链接:https://www.haomeiwen.com/subject/iemfkttx.html