“类族”可以隐藏“抽象基类”背后的实现细节。可以灵活应对多个类,将它们的实现细节隐藏在抽象基类后面,以保持接口简介。用户无需自己创建子类,只需调用基类方法来创建即可。
创建类族
// 基类头文件
typedef NS_ENUM(NSUInteger, EOCEmployeeType)
{
EOCEmployeeTypeDeveloper,
EOCEmployeeTypeDesigner,
EOCEmployeeTypeFinance
};
@interface EOCEmployee : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger salary;
+ (EOCEmployee *)employeeWithType:(EOCEmployeeType)type;
- (void)doADayWork;
@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)doADayWork
{
// 子类实现
}
// 子类实现文件
@implementation EOCEmployeeDeveloper
- (void)doADayWork
{
NSLog(@"EOCEmployeeDeveloper");
}
@end
// 子类实现文件
@implementation EOCEmployeeDesigner
- (void)doADayWork
{
NSLog(@"EOCEmployeeDesigner");
}
@end
// 子类实现文件
@implementation EOCEmployeeFinance
- (void)doADayWork
{
NSLog(@"EOCEmployeeFinance");
}
@end
// 使用
EOCEmployee *developer = [EOCEmployee employeeWithType:EOCEmployeeTypeDeveloper];
[developer doADayWork];
EOCEmployee *designer = [EOCEmployee employeeWithType:EOCEmployeeTypeDesigner];
[designer doADayWork];
EOCEmployee *finance = [EOCEmployee employeeWithType:EOCEmployeeTypeFinance];
[finance doADayWork];
输出:
2018-08-09 23:42:52.766696+0800 Demo[20792:1037824] EOCEmployeeDeveloper
2018-08-09 23:42:57.681192+0800 Demo[20792:1037824] EOCEmployeeDesigner
2018-08-09 23:43:00.393383+0800 Demo[20792:1037824] EOCEmployeeFinance
上面的例子,基类实现了一个“类方法”,该方法根据不同的类型创建不同的子类对象。这是“工厂模式”,是创建类族的办法之一。
Cocoa里的类族
系统框架有许多类族,大部分collection类都是类族,如NSArray和NSMutableArray。有两个抽象基类,一个用于不可变数组,一个用于可变数组。尽管具备公共接口的类有两个,但仍然可以合起来算作一个类族。不可变的类定义对所有数组都通用的方法,可变的类则定义只适用于可变数组的方法。两个类共属同一类族,这意味着两者在实现各自类型的数组时可以同用实现代码。
id maybeArray = /**...*/;
if ([maybeArray class] == [NSArray class]) {
}
说明:
NSArray是个类族,其中if语句永远不可能为真。[maybeArray class]返回的类绝不可能是NSArray,因为由NSArray的初始化方法所返回的那个实例其类型是隐藏在类族公共接口后面的某个内部类型。
// 用下面的类型信息查询方法判断
if ([maybeArray isKindOfClass:[NSArray class]]) {
}
像NSArray这样的类族新增子类,需要遵守的规则:
1、子类应该继承自类族中的抽象基类。
2、子类应该定义自己的数据存储方法。
3、子类应当覆写超类文档中指明需要覆写的方法。