文章目录
协议
协议是OC的知识点之一,其作用类似于接口,用于定义多个类应该组瘦的规范
规范、协议And接口
-
- OC语言中的协议的作用就相当于其他语言的接口作用
- OC语言中的协议的作用就相当于其他语言的接口作用
-
- 同一个类的内部状态数据,各种方法的实现细节完全相同,类是一种具体的实现体,而协议则定义了一种规范、
协议之规定着疲累中必须提供某些方法,提供这些方法的类就可以满足实际需要
协议不提供任何实现
这样理解协议
- 协议定义的是多个类共同的公共行为规范,这些行为与外部交流的通道,这就意味着协议里通常定义的是一组共用方法,但协议不为这些方法进行实现,实现交给类完成
使用类别实现非正式协议
当某个类实现NSObject的该 类别是,就需要实现该类别下的所有方法,这种基于NSObject定义的类别可以认为是 非正式协议
非正式协议实例
#import <Foundation/Foundation.h>
//协议
@interface NSObject (eatable)
-(void) taset;
@end
//子类
@interface fkapple : NSObject
@end
@implementation fkapple
// 协议里方法的实现
-(void) taset {
NSLog(@"这个苹果好吃滴很");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
fkapple *apple = [[fkapple alloc] init];
[apple taset];
}
return 0;
}
//打印
2022-05-21 16:19:19.766639+0800 OC协议与委托[5348:759981] 这个苹果好吃滴很
Program ended with exit code: 0
关于这个代码
- 从上面的代码可以看出 fkapple 类实现了taste方法,这样子fkapple就相当于遵守了eatable协议,接下来把fkapple类当eatabe对象调用
- 如果上面的fkapple类不实现taste方法,并且非正式协议本身彬哥密友实现该方法,那么该程序运行时就报错
这就是我注释了taste的实现并且在协议里也没有实现,希望读者注意
正式协议的定义
- 和定义类有区别的是正式协关键字议不在用@interface 和@implementation关键字,
- 使用@protocol关键字
正式协议@protocol语法
@protocol 协议名 <父协议1,父协议2> {
0到多个方法的定义
}
语法说明
对上面语法格式的详细说明如下。
- 协议名应与类名采用相同的命名规则。即如果仅从语法角度来看,协议名只要是合法的标识符即可:如果要遵守 Objective-C可读性规范,则协议名应由多个有意义的单词连接而成,每个单词首字母大写,单词与单词之间无须任何分隔符。
- 一个协议可以有多个直接父协议,但协议只能继承协议,不能继承类。
- 协议中定义的方法只有方法签名,没有方法实现;协议中包含的方法既可是类方法,也可是实例方法
前面己经说过了,协议定义的是多个类共同的公共行为规范,因此,协议里所有的方法都具有 公开访问权限
正式协议实例
//2.正式协议的定义
#import <Foundation/Foundation.h>
//1.定义一个fkOutput协议
@protocol fkOutput
//该协议的2个方法
//只要某个类满足下面的方法
-(void) output;
-(void) addData: (NSString*) msg;
@end
//2.定义一个fkproductable协议
@protocol fkproductable
// 该协议的方法返回产品的生产时间
//----------无论是哪种产品都应该提供一个getProduceTime 方法开获取该产品的生产时间
- (NSDate*) getProduceTime;
@end
//3.定义一个打印机协议 还协议同时继承上面的两个协议
@protocol fkPrintable <fkOutput, fkproductable>
//这里可以看出协议完全支持多继承,记一个协议可以多很多个父协议
//-------类似的,子协议继承某个父协议,将会获得父协议的所有方法
//打印机方法
-(NSString*) printColor;
@end
正式协议特点
- 这里可以看出协议完全支持多继承,记一个协议可以多很多个父协议
类似的,子协议继承某个父协议,将会获得父协议的所有方法
实现协议
- 在类的接口部分可以指定该类继承的父类及遵守的协议
实现协议的语法
@interface 类名 :父类<协议1,协议2.。。。。>
- 这里同样可以看出 一个类可以同时遵守多个协议
实现类
- 为fkprintable 协议 提供一个实现类:fkPrinter
/实现协议的类 - fkPrinter
//1.接口部分
@interface fkPrinter : NSObject <fkPrintable>
@end
//
//2。实现部分
@implementation fkPrinter {
NSString* printData[30];//数组记录所有需要缓存的打印数据
//记录当前需要打印的作业数
int dataNum;
}
-(void) output {
//需要打印的作业还有-循环继续
while (dataNum > 0) {
NSLog(@"打印机使用%@打印 :%@", self.printColor, printData[0]);
//剩余作业减一
dataNum --;
//作业整体向前移动一位
for (int i = 0; i < dataNum; i++) {
printData[i] = printData[i + 1];
}
}
}
-(void) addData :(NSString*) msg {
if (dataNum >= 30) {
NSLog(@"输出队列嘛满了,添加失败");
} else {
printData[dataNum ++] = msg;
}
}
-(NSDate*) getProduceTime {
return [[NSDate alloc] init];
}
-(NSString*) printColor {
return @"无敌炫酷缤纷大红色";
}
@end
//fkprinter类的实现 实现了fkprintable协议,并且也实现了fkoutput fkproductable两个父协议的所有方法,
//假如实现类未实现协议中的printfColor方法 编译器会如下警告
int main() {
@autoreleasepool {
// 创建一个对象
fkPrinter* p1 = [[fkPrinter alloc] init];
// 调用fkPrinter 对象的方法
[p1 addData:@"疯狂lyt讲义"];
[p1 addData:@"疯狂iOS学习!"];
[p1 output];
[p1 addData:@"疯狂3g都在学习"];
[p1 addData:@"疯狂iOS组今天没人!"];
[p1 output];
// p1程序是fkprinter对象,该对象包含上面3个i协议的方法,因此可以调用3个协议中的方法
}
}
2022-05-21 17:34:38.703607+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂lyt讲义
2022-05-21 17:34:38.703805+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂iOS学习!
2022-05-21 17:34:38.703825+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂3g都在学习
2022-05-21 17:34:38.703838+0800 OC协议与委托[5482:797126] 打印机使用无敌炫酷缤纷大红色打印 :疯狂iOS组今天没人!
Program ended with exit code: 0
- p1程序是fkprinter对象,该对象包含上面3个i协议的方法,因此可以调用3个协议中的方法
使用协议来定义变量
-
若果程序需要使用协议来定义变量,有如下两种语法
NSObject<协议1,协议2....>* 变量 id<协议1,协议2....> 变量;
注意:
使用上面语法格式定义的变量,它们编译时类型仅仅是所遵守的协议剋下,因此只能调用该协议中定义的方法
协议定义变量实例
int main() {
@autoreleasepool {
//创建一个fkprinter对象,当成fkproductable使用
//1.NSObject<协议1,协议2....>* 变量语法
NSObject<fkproductable> *p = [[fkPrinter alloc] init];
// 调用fkproductable 协议中定义的方法
NSLog(@"%@", p.getProduceTime);
//2. id<协议1,协议2....> 变量;
//创建一个fkprinter对象,当成fkoutput使用
id<fkOutput> out = [[fkPrinter alloc] init];
[out addData:@"勒布朗"];
[out addData:@"扬尼斯"];
[out addData:@"lyt"];
[out addData:@"阿道"];
[out output];
}
}
关于正式协议与非正式协议
对比正式协议与非正式协议,不难发现存在如下差异。
- >非正式协议通过为 NSObject 创建类别来实现:而正式协议则直接使用@protocol 创建。
- >遵守非正式协议通过继承带特定类别的 NSObject 来实现:而遵守正式协议则有专门的Objective-C 语法。
- >遵守非正式协议不要求实现协议中定义的所有方法:而遊守正式协议则必须实现协议中定义的所有方法。
为了弥补遵守正式协议必须实现协议的所有方法造成的灵活性不足,Objective-C 2.0 新增了@optional、 @required 两个关键字,其作用如下。
-
@optional:位于该关键字之后、@optional 或@end 之前声明的方法是可选的•实现类既可选择实现这些方法,也可不实现这些方法。
@required: 位于该关键字之后、@required 或@end 之前声明的方法是必需的实现
类必须实现这些方法。如果没有实现这些方法,编译器就会提示警告。@required 是默认行为@protocol fkoutput @optional (void) output; //由于@optiona关键字所以可选择的实现output @required (void) addData :(NSString*) msg; // addData 必须实现否则系统警告 @end
有了@optional @required 关键字 正式协议可以完全替代非正式协议
委托和协议
协议体现的是一种规范,定义协议的类可以吧协议定义的方法委托给实现协议的类,这样可以让类的定义具有更好的通用性