一、isEqual的作用
isEqual的作用:判断两个对象是否相等
对于基本类型, ==运算符比较的是值;
对于对象类型, ==运算符比较的是对象的地址(即是否为同一对象)
Objective-C和Java
不支持运算符重载, C++
支持运算符重载,这样的话可以在运算符重载的时候做判断
二、重写isEqual方法
Cocoa Framework中定义的类型,
NSString isEqualToString
NSDate isEqualToDate
NSArray isEqualToArray
NSDictionary isEqualToDictionary
NSSet isEqualToSet
isEqual方法已经实现好了。
对于自定义类型来说, 通常需要重写isEqual方法
首先定义TestModel类如下
@interface TestModel : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *color;
@end
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if (![object isKindOfClass:[TestModel class]]) {
return NO;
}
return [self isEqualToTestModel:(TestModel *)object];
}
- (BOOL)isEqualToTestModel:(TestModel *)tModel {
if (!tModel) {
return NO;
}
BOOL equalName = (!self.name && !tModel.name) || [self.name isEqualToString:tModel.name];
BOOL equalColor = (!self.color && !tModel.color) || [self.birthday isEqualToString:tModel.color];
return equalName && equalColor;
}
主要步骤:
1: ==运算符判断是否是同一对象, 同一对象必然完全相同
2: 判断是否是同一类型, 可以提高判等的效率, 还可以避免隐式类型转换带来的潜在风险
3: 通过封装的isEqualToTestModel方法, 提高代码复用性
4: 判断TestModel是否是nil, 做参数有效性检查
5: 对各个属性分别使用默认判等方法进行判断
6: 返回所有属性判等的与结果
三、重写hash方法
hash方法只在对象被添加至NSSet和设置为NSDictionary的key时会调用
NSSet添加新成员时, 需要根据hash值来快速查找成员, 以保证集合中是否已经存在该成员
NSDictionary在查找key时, 也利用了key的hash值来提高查找的效率
hash方法主要是用于在Hash Table查询成员用的。
为了优化判等的效率, 基于hash的NSSet和NSDictionary在判断成员是否相等时, 会这样做
第一步: 集合成员的hash值是否和目标hash值相等, 如果相同进入第二步判断, 如果不等, 直接判断不相等
第二步: hash值相同(第一步)的情况下, 再进行对象判等, 作为判等的结果
hash值是对象判等的必要非充分条件
- (NSUInteger)hash {
return [super hash];
}
//这样重写hash方法,是有隐患的。
//[super hash]返回的就是该对象的内存地址
//如果两个对象地址不同,但是内容完全一样,此时就都能加入NSSet了
Mattt Thompson在Equality中给出的结论就是
In reality, a simple XOR over the hash values of critical properties is sufficient 99% of the time(对关键属性的hash值进行位或运算作为hash值)
对于TestModel
- (NSUInteger)hash {
return [self.name hash] ^ [self.color hash];
}
参考文章:
Mattt Thompson
Equality
NSObject的hash方法
浅拷贝深拷贝以及 Hash/Equal