OC 对象等同性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OC 对象等同性相关的知识,希望对你有一定的参考价值。

参考技术A

根据 等同性 来比较对象是一个非常有用的功能。我们常用的 == 操作符比较,但是 == 比较的是指针本身,而不是其所指的对象。如果两个对象指针不同,但是其它的所有属性等全都相同,这两个对象可以说是 等同的 。
常见的比较方法有NSString、NSArray、NSDictionary的比较方法‘;它们不是比较指针,而是比较对象除指针之外的。

就拿 isEqualToArray: 来说

结果:

说明 array1 和 array2 是两个不同的对象(指针不同),却是两个等同的对象。

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

NSObject类对这两个方法的默认实现是:当且仅当对象的 “指针值” 完全相等的时候,这两个对象才相等。
这就会出现一个问题:如果我们希望一个 NSSet 中不存在等同的对象,而默认的 isEqual 和 hash 方法只会根据指针来判断,依然会把指针不同的等同对象放入Set中,显然,这无法做到我们想要的效果。所以现在我们要重写这两个方法。

同时重写 isEqual: 方法

什么是哈希码?
哈希码并不是完全唯一的,它是一种算法,让同一个类的对象按照自己不同的特征尽量的有不同的哈希码,但不表示不同的对象哈希码完全不同。也有相同的情况,看程序员如何写哈希码的算法。

根据等同性约定:
若两个对象等同,则起哈希码也相等,但是两个哈希吗相同的对象却不一定相等。

所以,相等的对象,必须有相等的哈希码,要尽量让不同对象的哈希码不会重复;
我们可以根据对象的属性值,生成哈希码;但是这样生成的哈希码依然会有重复的可能,但是并不会有太大的影响。

我们知道, isEqual: 方法或者 isEqualToPeople: 方法是会被程序员主动调用以判断对象是否等同,但是 hash 方法就没有 isEqual 方法的存在感那么强了。

这个问题可以被解释成这样:
何时需要调用对象的哈希码,作为或者生成一个识别码,用以识别不同的对象。
我们知道,字典是根据key来寻值的,所以一个字典里不能有相同的key。
1、当对象作为字典的key值时,会调用 hash 方法,帮助对象称为字典中独一无二的key

注意实现对象的 copyWithZone 方法

2、 NSSet 是不允许有重复的对象的,所以向 NSMutableSet 中添加对象时,会调用对象的 hash 方法,用以比较该对象是否已存在于集合中。

需要注意的是:把可变对象加入到集合set中后,尽量不要改变其哈希码了
原因:

我们上面定义了 hash 方法的实现,hash码是根据People对象的name和age来设定的,所以p3和p4是可以加入到集合set4中的。
现在,我们来更改一下p4,使p4和p3的哈希码相同,看看会发送什么?

此时,p3和p4是 等同的 。

我们看到, 不能存在重复对象的Set中居然存在了两个等同的对象!

那么我们如何把这两个等同的对象,去掉一个呢?

结果:

通过 copy 方法,深拷贝了一个全新的集合,这个新集合就像逐个向新集合中添加对象而创建出来的。这个问题还是根据开发者当前的需求从而决定是否需要对set进行 去重操作 。

以上是关于OC 对象等同性的主要内容,如果未能解决你的问题,请参考以下文章

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

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

iOS 一个对象的等同性

《Effective Objective-C 2.0 》 阅读笔记 item8

OC1(类和对象)

OC面向对象—继承