iOS -- Effective Objective-C 阅读笔记 ,5

1: 理解 '对象等同性' 概念

理解: 根据'等同性' 来比较对象是一个非常有用的功能, 不过按照 == 操作符比较出来的结果未必是我们想要的, 因为该操作比较的是两个指针本身, 而不是其所指的对象, 应该使用 NSObject 协议中声明的 'isEqual' : 方法来判断两个对象的等同性, 一般来说, 两个类型不同的对象总是不相等的, 如果已经知道两个手册对象都属于同一个类, 那么就可以使用这种方法

NSObject 协议有两个判断等同性的关键方法

- (BOOL) isEqua:l(id)object;

- (NSInteger)hash;

NSObject 类对这两个方法的默认实现是: 当且仅当 '其指针' 完全相等时, 这两个对象才相等, 如果 'isEqual' 方法判定两个对象相等, 那么其 'hash' 方法也必须返回同一个值, 但是, 如果两个对象那个的 hash 方法返回同一个值, 那么 'isEqual' 方法未必会认为两个值相等.

如果在自定义的对象中覆写这些方法, 首先,直接判断两个指针是相等, 若想等, 则其均指向同一对象, 所受测的对象也必定相等, 接下来, 比较两对象所属的类, 若不属于同一类, 则量对象不相等, 不过, 有时候我们可以认为, 一个类实例 可能与其子类实例相等, 所以要考虑这种情况, 最后,检测每个属性是否相等.

特定类所具有的等同性判定方法

数组和字典也具有特殊的等同性判定方法, isEqualToArray: isEqualToDictionary:

2: 以 '类族模式' 隐藏实现细节

'类族' 是一种很有用的模式 (也叫做 '类别方法'), 可以隐藏 '抽象基类 ' 背后的实现细节, OC 的系统框架 UIKit 中有一个名为 UIbutton 的类, 想要创建按钮, 需要实现下面这个 ' 类方法'

+ (UIButton)buttonWithType:(UIButtonType)type;

该方法所返回的对象,其类型取决于传入的按钮类型, 然而, 不管返回什么类型的对象,他们都继承自同意基类, UIButton, 这么做的意义在于, UIBUtton 类的使用者无需关心创建出来的按妞妞具体属于那个子类, 也无需创建子类实例, 只需要调用基类方法来创建即可.

创建类族

首先定义 抽象基类

typedef NS_ENUM(NSUINteger, EOCEmploeeType){

EOCRploeeTypeDeveloper,

EOCRploeeTypeDesigner,

EOCRploeeTypeFinance

};

@interface EOCEmploee: NSObject

@property (copy) NSString * name;

@property NSUinteger salary;

+ (EOCEployee*)employeeWithType:(EOCEEmployee)type;

@end

@implementation EOCEmplyee

+ (EOCEmployee*)employeeWithType:(EOCEEmployee)type{

switch (type){

case EOCRploeeTypeDeveloper:

return [EOCRploeeTypeDeveloper new];

break;

case EOCRploeeTypeDesigner:

return [EOCRploeeTypeDesigner new];

break;

case EOCRploeeTypeFinance:

return [EOCRploeeTypeFinance new];

break;

}

}

@end

在 本例 中, 基类实现了一个 '类方法', 该方法根据待创建的 实例类别 分配好对应的 类实例, 这种工厂模式 是创建嫘祖的办法之一.

cocoa 里的类族

系统框架中有许多类族, 大部分 collection 类 都是某个类族中的抽象基类, 例如 NSArray 与 NSMutableArray.

像 NSArrray 这样的类的背后其实是个类族, 明白这一点很重要, 否则或出现以下代码

id mutableArray = [];

if([mutableArray class] == [NSArray class]){

}

要知道 NSArray 是个类族, 其中的 if 语句永远不可能为真, [mutableArray class] 所返回的类型绝不可能是 NSArray 本身, 因为由 NSArray 的初始化方法所返回的那个实例其实是隐藏在类族公共接口 侯曼的内部实例.

想要判断某个实例所属的类是否位于类族之中, 可以使用 类型信息查询方法 ' isEqualOFClass:'

// 我们有时候需要向类族中新增实体子类, 不过需要注意, 在 Employee 这个例子中, 若是没有 '工厂方法'的源代码, 就无法向其中新增类别.

然而向 Cocoa 中 NSArray 这样的类族来说, 还是可以新增子类的, 但是需要遵守几条规则,

(1) 子类应该继承自 类族中的抽象基类

若想编写 NSArray 类族的子类, 则需要令其继承自不可变数组的基类 或 可变数组的基类

(2) 子类应该定义自己的数据存储方式

(3)子类应当覆写超类文档中指明覆写的方法

总结:

类族模式 可以把实现细节隐藏在一套简单的公共接口后面

系统框架中经常使用类族

从类族的公共抽象基类中继承子类时要当心, 若有开发文档, 则应首先阅读.