类族是一种很有用的模式,可以隐藏抽象基类背后的实现细节,比如UIButton类,要想创建按钮要使用类方法
+(UIButton*)buttonWithType:(UIButtonType)type;
该方法返回对象取决于按钮的类型,他们都继承自同一个基类,这样是使用者不许关兴创建出来的按钮具体属于哪个子类。
现在举例来演示如何创建类族,假设有一个处理雇员的类,每个雇员都有“名字”和“薪水”这两个属性,管理者可以命令其执行日常工作,但是,各种雇员的工作内容却不同,经理在带领雇员做项目时,无须关心每个人如何完成其工作,仅需指示其开工即可。
首先要定义抽象基类:
typedef NS_ENUM(NSUInteger, EOCEmployeeType) {
EOCEmployeeTypeDeveloper,
EOCEmployeeTypeDesigner,
EOCEmployeeTypeFinance,
};
@interface EOCEmployee : NSObject
@property (copy) NSString *name;
@property NSUInteger salary;
// Helper for creating Employee objects
+ (EOCEmployee*)employeeWithType:(EOCEmployeeType)type;
// Make Employees do their respective day's work
- (void)doADaysWork;
@end
@implementation EOCEmployee
+ (EOCEmployee*)employeeWithType:(EOCEmployeeType)type {
switch (type) {
case EOCEmployeeTypeDeveloper:
return [EOCEmployeeDeveloper new];
break;
case EOCEmployeeTypeDesigner:
return [EOCEmployeeDesigner new];
break;
case EOCEmployeeTypeFinance:
return [EOCEmployeeFinance new];
break;
}
}
- (void)doADaysWork {
// Subclasses implement this.
}
@end
每个“实体子类”(concrete subclass)都从基类继承而来,例如:
@interface EOCEmployeeDeveloper : EOCEmployee
@end
@implementation EOCEmployeeDeveloper
- (void)doADaysWork {
[self writeCode];
}
@end
我们经常需要向类族中新增实体子类,不过这么做的时候得留心。在Employee这个例子中,若是没有“工厂方法”(factory method)的源代码,那就无法向其中新增雇员类别了。然而对于Cocoa中NSArray这样的类族来说,还是有办法新增子类的,但是需要遵守几条规则。这几条规则如下。
子类应该继承自类族中的抽象基类。
若要编写NSArray类族的子类,则需令其继承自不可变数组的基类或可变数组的基类。
子类应该定义自己的数据存储方式。
开发者编写NSArray子类时,经常在这个问题上受阻。子类必须用一个实例变量来存放数组中的对象。这似乎与大家预想的不同,我们以为NSArray自己肯定会保存那些对象,所以在子类中就无须再存一份了。但是大家要记住,NSArray本身只不过是包在其他隐藏对象外面的壳,它仅仅定义了所有数组都需具备的一些接口。对于这个自定义的数组子类来说,可以用NSArray来保存其实例。
子类应当覆写超类文档中指明需要覆写的方法。
在每个抽象基类中,都有一些子类必须覆写的方法。比如说,想要编写NSArray的子类,就需要实现count及“objectAtIndex:”方法。像lastObject这种方法则无须实现,因为基类可以根据前两个方法实现出这个方法。
在类族中实现子类时所需遵循的规范一般都会定义于基类的文档之中,编码前应该先看看。