本篇文章介绍OC的分类和协议
分类是这样一种设计,对于一个已经存在的类A,这个类可能是自己写的,或者是第三方的,甚至是系统提供的。这个类对我们很有用,但是,我们有些想要的功能在这个类里却没有实现。这个时候我们可以使用分类的功能对类A进行扩展。使用语法如下:
// 这个是A.h文件,定义了A的功能
@interface A : NSObject
{
// 定义了一个实例变量,可以被子类使用
int iA1;
}
@property int pA1;
-(void) A1;
@end
// 这是是分类A+B.h文件
#import "A.h"
// 分类的写法是这样的,主类名(分类名)
// 必须import主类名
@interface A(B)
{
int iA_B1;
}
@property int pA_B1;
-(void)A_B1;
@end
分类完成后,如果我们想使用分类,必须import 分类的头文件
#import <Foundation/Foundation.h>
#import "A+B.h"// 这里需要包含分类名的头文件
int main(int argc, const char * argv[]) {
@autoreleasepool {
A* a = [[A alloc] init];
[a A_B1];// 可以看到,A的实例可以调用分类的方法
}
return 0;
}
注意,我们在定义分类B的时候不需要列出类A继承的类。
分类有如下特性:
readonly
限定符,这样就不会警告了。如果我们需要将分类单独保存到一个文件,通常采用A+B的形式,其中A是主类名,B是分类名
有一种特殊的情况是创建一个未命名的分类,实现方法就是在定义分类时在括号中不指定名字。这种特殊的语法称为类的扩展,类的扩展一般是定义在主类的实现文件中,下面是类扩展的一个例子
// A.h文件
@interface A : NSObject
{
int iA1;
}
@property int pA1;
-(void)A1;
@end
// A.m文件
#import "A.h"
// 这是类A的扩展
@interface A()
{
int iA_1;
}
@property int pA_1;
-(void)A_1;
@end
@implementation A
-(void)A1
{
NSLog(@"print A1");
}
-(void)A_1
{
NSLog(@"print A_1");
}
@end
如果我们在类的实现中定义类的扩展,扩展类有下面的属性:
类的扩展中定义的属性,实例变量和方法都是私有的,只能在当前类内部访问,包括子类
。通过这种方式,我们可以定义私有的东西。协议是一组方法的接口
协议采用下面的格式进行定义
@protocol 协议名称
// 这里定义协议的接口
@required
@optional
@end
如果要在一个类中使用协议:
看下面的例子:
首先是定义协议,下面的协议定义在A.h中
@protocol CALDelegate
@required
-(int)add:(int) a with:(int) b;
-(int)sub:(int) a with:(int) b;
-(int)times:(int) a with:(int) b;
-(int)div:(int) a with:(int) b;
@optional
-(int)add1:(int) a with:(int) b;
-(int)sub1:(int) a with:(int) b;
-(int)times1:(int) a with:(int) b;
-(int)div1:(int) a with:(int) b;
@end
注意:
@required
:对于遵守协议名的类来说必须实现的方法列表@optional
:对于遵守协议名的类来说可以选择实现的方法列表下面是遵守协议的类,有两种方式,一种通过继承:
@interface A1 : A<CALDelegate>
另一种通过包含A.h头文件
#import "A.h"
@interface C : NSObject<CALDelegate>
注意:协议是无类的,谁都可以遵守协议。
可以使用conformsToProtocol:
方法检查一个对象是否遵循某项协议,看下面例子:
A1* a = [[A1 alloc] init];
if([a conformsToProtocol:@protocol(CALDelegate)])
{
NSLog(@"A1 conform Protocol CALDelegate");
}
注意:
所以,一般情况下,我们如果调用协议下的方法,需要提前判断当前类是否已经实现了该方法。
代理是协议的一种高级用法,通常的使用方式如下:
// A.h
@protocol CALDelegate
@required
-(int)add:(int) a with:(int) b;
-(int)sub:(int) a with:(int) b;
-(int)times:(int) a with:(int) b;
-(int)div:(int) a with:(int) b;
@optional
-(int)add1:(int) a with:(int) b;
-(int)sub1:(int) a with:(int) b;
-(int)times1:(int) a with:(int) b;
-(int)div1:(int) a with:(int) b;
@end
@interface A : NSObject
{
int iA1;
}
@property int pA1;
@property NSObject<CALDelegate>* delegate;
-(void)A1;
-(void)print:(int)a with:(int)b with:(int)type;
@end
其中@property NSObject<CALDelegate>* delegate;
这行代码就是定义代理类的属性,说明代理类需要是NSObject或者子类,并且遵循CALDelegate协议// C.m
@implementation C
-(void)print
{
A* a= [[A alloc] init];
if(!a.delegate)
{
// 代理类注册
a.delegate = self;
}
// 在协议类中就可以使用代理类实现的协议方法了
[a print:1 with:1 with:1];
[a print:1 with:1 with:2];
[a print:1 with:1 with:3];
[a print:1 with:1 with:4];
}
// 后面是对协议方法的实现
// ...