protocol概念及基本使用
1、protocol的基本概念
协议:一些方法的声明,一般写到一个.h的头文件中,供其他的类或者协议去遵守。
在OC中,接口是有一个叫做协议的protocol来实现的。它与java不同的是,它可以声明一些必须实现的方法和选择实现的方法,有选择性的。
2、protocol的使用流程
协议的使用流程:定义协议—》再类中采用指定的协议—》实现协议中对应的方法(选择性的)
1)定义协议
@protocol 协议名称 <NSObject> //默认遵守NSObject协议
//方法声明列表
@end
2)采用协议
1、类遵守协议
创建类的时候遵守某个或者几个协议
@interface 类名 :父类<协议名称>
@end
@interface 类名 :父类<协议名称1,协议名称2>
@end
2、协议遵守协议
某个协议也遵守某个或者某些协议,一个协议可以遵守其他多个协议,
多个协议之间用逗号','隔开
@protocol 协议名称<其他协议名称>
@end
3)实现对应的方法(必须要实现的)
结论:当我们遵守了某个协议后,就相当于这个类有了协议中所有的方法声明
protocol的其他用法
1、protocol的使用注意
1)protocol:就一个用途,用来声明一大堆的方法(不能声明成员变量),不能写实现
2)只要某个类遵守了这个协议,就拥有了这个协议的所有方法声明
3)只要父类遵守某个协议,那么子类也遵守
4)protocol声明的方法可以让任何类去实现,protocol就是协议
5)OC不能继承多个类(单继承),但是可以遵守多个协议。继承(:),遵守协议(<>)
6)基协议:<NSObject>是基协议,是最根本最基本的协议,其中声明了很多最基本的方法
7)协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一个协议中的方法声明
2、protocol基协议介绍
NSObject是一个积累,最根本最基本的类,任何其他类最终都要继承它。它还有名字也叫NSObject的协议
,它是一个基协议,最根本最基本的协议。
建议每个新的协议都要遵守NSObject协议。
protocol中@required和@optional
@required和@optional是协议方法声明中的两个关键字
它们主要用于控制方法是否要实现(默认是@required),在大多数情况下,用途在于程序员之间的交流
//
必须要实现,不实现编译器报错
//
不加关键字,默认是要实现的
@required
-( void )run;
-( void )eat;
// 可以实现,也可以不实现
@optional
-( void )run;
-( void )eat;
// 可以实现,也可以不实现
@optional
-(void)fight;
protocol类型限制
1、protocol类型限制
1)给id类型增加限制
Girl
*mm = [
Girl
new
];
// 由于 id 类型可以接受任何类型的对象,要增加类型限制
//id< 协议名称 > ,限制 obj ,只能赋值遵守了 household 协议的对象
// 由于 id 类型可以接受任何类型的对象,要增加类型限制
//id< 协议名称 > ,限制 obj ,只能赋值遵守了 household 协议的对象
id<houseHoldProtocol> obj = mm;
2)给具体对象增加限制
1、
Girl
<
houseHoldProtocol
> *obj = mm;//在遵守协议的前提下,对象还必须是合理地
2、
@property
(
nonatomic
,
strong
) Dog<
suanShuProtocol> *dog;//人拥有会算数的狗,任意的狗就不可以
2、id和instancetype的区别
1)instancetype只能作为函数或者方法的返回值
2)id能作为方法或者函数的返回值、参数类型,也能用来定义变量
3)instancetype对比id的好处:能够精确地限制返回值的具体类型
protocol代理设计模式
代理模式:婴儿和保姆之间有个协议,保姆遵守该协议,于是保姆就需要实现该协议中的条款,从而成为代理人。
错误:linker command failed with exit code 1 (use -v to see invocation)
1)重复包含头文件
2)第三方库
1、protocol代理设计模式概念
MVC模式:m-model(模型)
v-view(视图)
c-controller(控制器)
代理模式:传入的对象,代替当前类完成了某个功能。
利用协议实现代理模式的主要思路:
1)定义一个协议,里面声明代理类需要实现的方法列表
2)创建一个代理类(比如BaoMu),遵守上面的协议
3)在需要代理的类(Baby)中,定义一个对象,类型为id,且遵守代理协议的成员变量
4)在Baby类中调用成员变量_delegate(代理对象)的方法,调用代理类的方法
5)main.m或其他使用Baby类的文件中,为成员变量赋值
2、protocol代理模式的应用场合
1)当对象A发生了一些行为,想告诉对象B(让对象B称为对象A的代理对象)—》通知场合
2)对象B想监听对象A的一些行为(
让对象B称为对象A的代理对象
)—》监听器场合
3)当对象A无法处理某些行为的时候,想让对象B帮忙处理(
让对象B称为对象A的代理对象
)—》自己不想或不能处理
思路实现例子:
1)协议:
#import
<Foundation/Foundation.h>
@class Baby ;
@protocol lookBabyProtocol < NSObject >
// 喂婴儿吃饭
-( void )feedBabyEat:( Baby *)baby;
// 哄婴儿睡觉
-( void )HongBabySleep:( Baby *)baby;
@class Baby ;
@protocol lookBabyProtocol < NSObject >
// 喂婴儿吃饭
-( void )feedBabyEat:( Baby *)baby;
// 哄婴儿睡觉
-( void )HongBabySleep:( Baby *)baby;
@end
2)代理类:
#import
<Foundation/Foundation.h>
//
保姆想成为婴儿代理人,必须遵守协议
#import "lookBabyProtocol.h"
@interface BaoMu : NSObject < lookBabyProtocol >
#import "lookBabyProtocol.h"
@interface BaoMu : NSObject < lookBabyProtocol >
@end
#import
"BaoMu.h"
#import "Baby.h"
@implementation BaoMu
// 喂婴儿吃饭
-( void )feedBabyEat:( Baby *)baby {
baby. blood += 10 ;
NSLog ( @" 保姆正在喂婴儿吃东西!体力值现在为 %.2f" , baby. blood );
}
// 哄婴儿睡觉
-( void )HongBabySleep:( Baby *)baby {
baby. sleep += 20 ;
NSLog ( @" 保姆正在哄婴儿睡觉!睡眠值现在为 %.2f" , baby. sleep );
}
#import "Baby.h"
@implementation BaoMu
// 喂婴儿吃饭
-( void )feedBabyEat:( Baby *)baby {
baby. blood += 10 ;
NSLog ( @" 保姆正在喂婴儿吃东西!体力值现在为 %.2f" , baby. blood );
}
// 哄婴儿睡觉
-( void )HongBabySleep:( Baby *)baby {
baby. sleep += 20 ;
NSLog ( @" 保姆正在哄婴儿睡觉!睡眠值现在为 %.2f" , baby. sleep );
}
@end
3)需要代理的类:
#import
<Foundation/Foundation.h>
@class
BaoMu
;
#import "lookBabyProtocol.h"
@interface Baby : NSObject
#import "lookBabyProtocol.h"
@interface Baby : NSObject
//
保姆、体力值、睡眠
@property
(
nonatomic
,
strong
)
BaoMu
<
lookBabyProtocol
> *bm;//此处代理对象一般为_delegate
@property
(
nonatomic
,
assign
)
float
blood;
@property ( nonatomic , assign ) float sleep;
// 吃、睡
-( void )wantEat;
-( void )wantSleep;
@property ( nonatomic , assign ) float sleep;
// 吃、睡
-( void )wantEat;
-( void )wantSleep;
@end
#import
"Baby.h"
#import "BaoMu.h"
@implementation Baby
-( void )wantEat {
NSLog ( @" 婴儿在哭 ..." );
// 保姆要喂他吃
[ self . bm feedBabyEat : self ];
}
-( void )wantSleep {
NSLog ( @" 婴儿在哭 ..." );
// 保姆要哄她睡
[ self . bm HongBabySleep : self ];
}
#import "BaoMu.h"
@implementation Baby
-( void )wantEat {
NSLog ( @" 婴儿在哭 ..." );
// 保姆要喂他吃
[ self . bm feedBabyEat : self ];
}
-( void )wantSleep {
NSLog ( @" 婴儿在哭 ..." );
// 保姆要哄她睡
[ self . bm HongBabySleep : self ];
}
@end
4)赋值:
#import
<Foundation/Foundation.h>
#import "BaoMu.h"
#import "Baby.h"
int main( int argc, const char * argv[]) {
@autoreleasepool {
BaoMu *baomu = [ BaoMu new ];
Baby *baby = [ Baby new ];
baby. bm = baomu;
baby. blood = 10 ;
baby. sleep = 10 ;
[baby wantEat ];
[baby wantSleep ];
}
return 0 ;
#import "BaoMu.h"
#import "Baby.h"
int main( int argc, const char * argv[]) {
@autoreleasepool {
BaoMu *baomu = [ BaoMu new ];
Baby *baby = [ Baby new ];
baby. bm = baomu;
baby. blood = 10 ;
baby. sleep = 10 ;
[baby wantEat ];
[baby wantSleep ];
}
return 0 ;
}
引入协议
@protocol 协议名;//类似@class的用法
1、要遵守这个协议的类,用@protocol 告诉编译器这时一个协议
2、在.m文件中,导入协议头文件
3、在main函数中,也要导入协议头文件