第8条:理解“对象等同性”这一概念
等同性
,按照”==”操作比较的是指针本身,而不是其所指的对象(指针不相等,但是对象可能相等)- 使用NSObject协议声明的
isEqual:
方法判断两个对象的等同性 - 通常,类型不同的对象总是不相等。若比较的对象为同一个类,可以使用对象的特殊“等同性判定方法”。NSString的
isEqualToString:
方法,调用比isEqual:
快 - NSObject协议中两个判断等同性的关键方法。默认实现:当且仅当其“指针值”完全相等时,对象相等。
isEqual:
判断对象相等,则hash
比返回相同hash值;反之未必。 - (BOOL)isEqual:(id)object;
- (NSUInteger)hash;
- 相等判断:指针是否相等>是否是同一个类>属性是否相等
特定类所具有的等同性判定方法
NSString
的isEqualToString:
NSArray
的isEqualToArray:
NSDictionary
的isEqualToDictionary
自定义等同性判定方法,无须检测参数类型,大大提速。
等同性判定的执行深度
需要决定根据整个对象判断等同性,还是其中几个字段来判断
容器中可变类的等同性
容器中放入可变类对象后,不该修改其内容,否则可能造成未知后果
要点
- 若想检测对象的等同性,请提供
isEqual:
与hash
方法 - 相同的对象必须具有相同的哈希码,但是相同哈希码的对象未必相同
- 不要盲目逐个检测每条属性,该根据具体需求定制检测方案
- 编写hash方法时,应该使用计算速度快而哈希码碰撞几率低的算法
第9条:以“类族模式”隐藏实现细节
隐藏“抽象基类”的实现细节
- 判断实例所属类是否位于类族之中,使用
类型信息查询方法
isKindOfClass:
- 向类族中新增子类规则
- 子类应该继承自类族中的抽象基类
- 子类应该定义自己的数据存储方式
- 子类应当覆写超类文档中指明需要覆写的方法
要点
- 类族模式可以把实现细节隐藏在一套简单的公共接口后面
- 系统框架中经常使用类族
- 从类族的公共抽象基类中继承子类时要当心,如有开发文档,则应首先阅读
第10条:在既有类中使用关联对象存放自定义数据
关联对象(Associated Object),给某对象关联其他对象,通过“键”区分。存储对象值的时候,指明“存储策略”,维护相应的“内存管理语义”
- 管理关联对象的方法
- void objc_setAssociatedObject(id object,void *key,id value,objc_AssociationPolicy policy) 以给定的键和策略为某对象设置关联对象值
- id objc_getAssociatedObject(id object,void *key) 根据给定的键从某对象中获取相应的关联对象的值
- void objc_removeAssociatedObjects(id object)移除指定对象的全部关联对象
- 设置关联对象值时,通常使用静态全局变量做键。两个键匹配到同一个值,二者指针必须完全相同
要点
- 通过“关联对象”机制把两个对象连起来
- 定义关联对象时可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”与“非拥有关系”
- 只有在其他做法不可执行时才应选用关联对象,因为通常会引入难于查找的Bug