Effective Objective-C 2.0 编写高质量iOS与OS X代码 对象等同性

本文介绍了如何在Objective-C中正确实现`isEqual:`和`hash`方法,确保对象等同性。重点在于根据类的具体需求定制比较逻辑,避免不必要的属性比较,并确保相同对象具有相同的哈希码。同时,文章提醒在容器中使用可变对象时,添加到集合后不应修改其哈希码,以防止容器内部状态混乱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 若想检测对象的等同性,请提供“isEqual”与“hash”方法。
- (BOOL)isEqual:(id)object
{
     if(self == object) return YES;
     if([self class] != [object class] ) return NO;
     ConcreteId *otherId = (ConcreteId*)object;
     if(![someProperty isEqual:otherId.someProperty])
          return NO;
     // ……… 比较其他属性值
     return YES;
}

① 特定类所具有的等同性判定方法
如果受测的参数与接收该消息的对象都属于同一类,那么就调用自己编写的判定方法。否则使用超类来判断。
- (BOOL)isEqual:(id)object
{
     if([self class] ==[ object class ])
     {     
          return [self isEqualToPerson:(EOCPerson*)object};
     }else {
          return [self isEqual:object];
     }
}

2. 相同的对象必须具备相同的哈希码,但是两个哈希码相同的对象却未必相同。

3. 不要盲目地逐个检测每条属性,而是应该依照具体需求来制定检测方案。

① 等同性判定的执行深度。
如果某个对象是从数据库创建出来的,其中就有可能有个属性是“唯一标识符”,这种情况下只需使用这个属性进行判断而无需全部属性都判断一遍。

4. 编写hash时,应该使用计算速度快而且哈希码碰撞几率低的算法。


5. 容器中可变类的等同性。
① 在容器中放入可变类对象的时候,就不应该再修改其哈希码了。
如果放入collection后其哈希码又变化了,那么其所在的这个“箱子数组”对它来说就是“错误”的。

使用NSMutableSet 和 NSMutableArray 对象测试一下。先把一个数组加入set中:
NSMutableSet *set = [NSMutableSet new];
NSMutableArray *arrayA = [@[@1, @2] mutableCopy];
[set addObject:arrayA];
NSLog(@“set = %@“,set);
// set = {((1,2))}

再向set加入一个数组,此数组与前一个数组所含的对象相同,顺序也相同:
NSMutableArray *arrayB = [@[@1, @2] mutableCopy];
[set addObject:arrayB];
NSLog(@“set = %@“,set);
// set = {((1,2))} 

此时仍只有一个对象,因为刚才要加入的那个数组对象和set中已有的数组对象相等,所以set并不会改变:
NSMutableArray *arrayC = [@[@1] mutableCopy];
[set addObject:arrayC];
NSLog(@“set = %@“,set);
// set = {((1),(1,2))}  

然后我们再改变arrayC的内容:
[arrayC addObject:@2];
NSLog(@“set = %@“,set);
// set = {((1,2),(1,2))}  

此时set中就包含了两个彼此相等的数组,根据set语义是不允许出现这种情况的。然后现在却无法保证这一点。
若是拷贝此set
NSSet *setB = [set copy];
NSLog(@“setB = %@“,setB);
// setB = {((1,2))} 

所以说,如果把某个对象放入set后又修改其内容,那么后面的行为将很难预测。


摘取自:《 Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法》,详细请购买书籍,支持作者及译者。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值