Objective-C的对象等同性
来源:互联网 发布:百度文库离线文件json 编辑:程序博客网 时间:2024/04/30 13:04
OC开发中我们常常需要比较两个对象是否相等,但是依靠==操作符进行比较的结果未必使我们想要的。因为实例对象本质上是指针,使用==符号实际上是比较两个指针指向内容本身是否相等,而不是比较指向对象。没有操作符重载的OC在基类NSObject协议中声明了方法isEqual和hash来比较对象,通过代码来演示isEqual的作用:
上面三个方法可以比较出==跟isEqual方法的区别,而除了这两个比较外还有一个isEqualToString方法,它跟isEqual有什么差别?
isEqualToString接收一个NSString的参数,用于判断两个字符串变量的值是否相等。如果传递给该方法的参数不是NSString类型,那么程序将会crash。对比isEqual方法,前者执行速度要比后者快,但是后者对于参数类型没有限制。另外,isEqualToString方法也是必须要创建的,这点会在下面进行讲解。
接下来就是hash函数,hash返回被测对象的哈希值:
两个对象也返回了同一个hash值,那么是否这意味着我们可以使用isEqual和hash两个方法任意一个来判断两个对象是否相等呢?答案是否。我们来推测一下isEqual的内部实现。因为OC对NSObject进行了封装,我们无法看到其实现文件,但能从功能上推测出来,我们定义一个Person类重写该方法:
我们可以看到,在otherPerson对象内部值改变之后,isEqual就返回了NO,说明了我们的重写是正确的。但是hash值在变量值发生变化之后依旧没有任何改变,这说明了我们无法通过hash值来判断两个对象是否相等。
我们再来看看对isEqual重写的函数,先判断两个指针是否指向同一块内存,如果是就返回正确。第二个判断是判断两个对象类型是否相同,在继承体系中,我们必须注意对比两个对象时,确保它们的类型是一致的。接着就对比内部成员的值,全部正确就返回比较成功。看起来这个方法非常成功,但是,这样的重写是错误的!
在苹果官方规定中有提及:如果isEqual方法判定两个对象相等,那么其hash方法也必须返回同一个值。而上面的代码运行中我们可以看到两个对象的哈希值是不一样的,而isEqual方法却返回了正确,这也说明了默认的hash值是以对象地址为原型进行算法修改的!而hash想要返回同样的值,意味着两个实例指针必须指向同一个对象或者我们重写hash方法。但是重写hash方法需要使用计算速度快而且哈希码碰撞概率低的算法,非常的麻烦。所以正常情况下我们都会改写isEqual方法,而这就说明了我们重写的isEqual函数中,从第一个判断开始,之后的全部要去掉。去掉的同时也说明了我们无法通过isEqual方法来对比两个同类型的不同对象的大小,所以这时候我们需要重新声明一个函数来判断,这就是为什么会出现上文中的isEqualToString方法。那么我们再次进行重写:
我们在自定义类时一定要记住对象等同性的规则,重写isEqual方法和响应的isEqualTo...方法有助于我们写出更健壮的代码。当然了,在容器中可变长类使用对象等同性时,可能造成意想不到的数据错误,这点在以后再细讲。
上面三个方法可以比较出==跟isEqual方法的区别,而除了这两个比较外还有一个isEqualToString方法,它跟isEqual有什么差别?
isEqualToString接收一个NSString的参数,用于判断两个字符串变量的值是否相等。如果传递给该方法的参数不是NSString类型,那么程序将会crash。对比isEqual方法,前者执行速度要比后者快,但是后者对于参数类型没有限制。另外,isEqualToString方法也是必须要创建的,这点会在下面进行讲解。
接下来就是hash函数,hash返回被测对象的哈希值:
两个对象也返回了同一个hash值,那么是否这意味着我们可以使用isEqual和hash两个方法任意一个来判断两个对象是否相等呢?答案是否。我们来推测一下isEqual的内部实现。因为OC对NSObject进行了封装,我们无法看到其实现文件,但能从功能上推测出来,我们定义一个Person类重写该方法:
我们可以看到,在otherPerson对象内部值改变之后,isEqual就返回了NO,说明了我们的重写是正确的。但是hash值在变量值发生变化之后依旧没有任何改变,这说明了我们无法通过hash值来判断两个对象是否相等。
我们再来看看对isEqual重写的函数,先判断两个指针是否指向同一块内存,如果是就返回正确。第二个判断是判断两个对象类型是否相同,在继承体系中,我们必须注意对比两个对象时,确保它们的类型是一致的。接着就对比内部成员的值,全部正确就返回比较成功。看起来这个方法非常成功,但是,这样的重写是错误的!
在苹果官方规定中有提及:如果isEqual方法判定两个对象相等,那么其hash方法也必须返回同一个值。而上面的代码运行中我们可以看到两个对象的哈希值是不一样的,而isEqual方法却返回了正确,这也说明了默认的hash值是以对象地址为原型进行算法修改的!而hash想要返回同样的值,意味着两个实例指针必须指向同一个对象或者我们重写hash方法。但是重写hash方法需要使用计算速度快而且哈希码碰撞概率低的算法,非常的麻烦。所以正常情况下我们都会改写isEqual方法,而这就说明了我们重写的isEqual函数中,从第一个判断开始,之后的全部要去掉。去掉的同时也说明了我们无法通过isEqual方法来对比两个同类型的不同对象的大小,所以这时候我们需要重新声明一个函数来判断,这就是为什么会出现上文中的isEqualToString方法。那么我们再次进行重写:
这次重写完之后就没错了。
我们在自定义类时一定要记住对象等同性的规则,重写isEqual方法和响应的isEqualTo...方法有助于我们写出更健壮的代码。当然了,在容器中可变长类使用对象等同性时,可能造成意想不到的数据错误,这点在以后再细讲。
0 0
- Objective-C的对象等同性
- Objective-C对象等同性的理解
- Objective-C中“对象等同性”的判定方法
- Objective-C——判断对象等同性
- Effetive Objective - C 1.Objective8.;理解对象等同性
- Effective Objective-C 2.0 编写高质量iOS与OS X代码 对象等同性
- Effective Objective-C 2.0 第8条:理解“对象等同性”概念
- 如何理解iOS的“对象等同性”
- iOS 对象等同性
- 对象等同性
- 对象等同性判断
- 引用等同性与对象等同性及对象复制
- iOS判断对象等同性
- ios开发之判断对象的等同性isEqual
- 判断对象的等同性isEqual和hash
- ios开发之判断对象的等同性isEqual
- hibernate之对象同一性和等同性
- iOS理解“对象等同性”这一概念
- 黑马程序员——c语言学习—作用域详解
- Android 遍历界面控件
- Android 文件下载
- Linux命令3——pwd
- 抓取网络json数据并存入mongodb(2)
- Objective-C的对象等同性
- Axure Mobile原型发布工具说明
- No CPU/ABI system image available for this barget
- unity之台湾游戏教父王俊博:做永远的抬轿人
- [CODEVS 3147] 矩阵乘法 2
- 关于项目
- NYOJ--60 谁获得了最高奖学金【水题】
- FFmpeg示例程序合集-Git批量获取脚本
- unity游戏之年度最佳游戏奖项名单公布