黑马程序员——OC中的协议:protocol

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
一、protocol介绍

(一)、protocol的概念

在OC中,我们会把一些方法的声明写到一个.h的头文件中,这就是protocol,也称为“协议”

协议中声明的方法有两种:

  • 必须实现
  • 选择实现
(二)、protocol的作用

供其他的类去遵守,如果一个类遵守了一个协议,就应该实现这个协议中定义的必须要实现的方法

二、protocol使用

(一)、protocol的使用流程

1、定义一个协议

@protocol xxx <NSObject>  默认情况下遵守NSObject协议
@end

2、遵守协议

1)遵守一个协议

先导入头文件

@interface 类名 :NSObject <xxx>
@end

2)遵守多个协议

@interface 类名 :NSObject <xxx,aaa,bbb>
@end

3、实现协议中的方法

见下面示例

(二)、protocol的基本使用

1、定义协议

baseProtocol.h

#import <Foundation/Foundation.h>
@protocol baseProtocol <NSObject>
// 声明一些方法
-(void)eat;
-(void)run;
@end
workProtocol.h
#import <Foundation/Foundation.h>
@protocol workProtocol <NSObject>
-(void) work;
@end

2、遵守协议

1)某个类遵守某个协议

Person.h

#import <Foundation/Foundation.h>
// 导入头文件
#import "baseProtocol.h"
@interface Person : NSObject<baseProtocol>

@end
2)某个协议遵守多个协议

Person.h

#import <Foundation/Foundation.h>
// 导入头文件
#import "baseProtocol.h"
#import "workProtocol.h"
@interface Person : NSObject<baseProtocol,workProtocol>

@end
3)协议遵守协议

baseProtocol.h

#import <Foundation/Foundation.h>
#import "workProtocol.h"
@protocol baseProtocol <NSObject,workProtocol> 
// 声明一些方法
-(void)eat;
-(void)run;
@end

3、实现协议中的方法

Person.m

#import "Person.h"
@implementation Person
//实现协议中声明的方法
-(void)eat{
    NSLog(@"人在吃");
}
-(void)run{
    NSLog(@"人会跑");
}
-(void) work{
    NSLog(@"人在工作");
}
@end
在main.m中使用

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //创建对象
        Person *p = [Person new];
        //调用协议中的方法
        [p run];
        [p eat];
        [p work];
    }
    return 0;
}

(三)、protocol的使用注意

1、Protocol:就一个用途,用来声明一大堆的方法(不能声明成员变量),不能写实现

2、只要某个类遵守了这个协议,就拥有了这个协议中的所有方法声明

3、Protocol声明的方法可以让任何类去实现,protocol就是协议

4、OC不能继承多个类(单继承)但是能够遵守多个协议。继承(:),遵守协议(< >)

5、基协议:<NSObject>是基协议,是最根本的协议,其中声明了很多最基本的方法,每个新的协议都要遵守基协议

6、只要父类遵守了某个协议,那么子类也要遵守

7、协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明

8、一个协议可以被多个类遵守

示例:Person类和Cat同时遵守AnimalProtocol协议

AnimalProtocol.h

#import <Foundation/Foundation.h>
@protocol AnimalProtocol <NSObject>
-(void)run;
@end

Cat.h

#import <Foundation/Foundation.h>
#import "AnimalProtocol.h"
@interface Cat : NSObject<AnimalProtocol>

@end

Person.h

#import <Foundation/Foundation.h>
#import "AnimalProtocol.h"
@interface Person : NSObject<AnimalProtocol>

@end

Cat.m

#import "Cat.h"
@implementation Cat
-(void)run{
    NSLog(@"猫在跑");
}
@end

Person.m

#import "Person.h"
@implementation Person
-(void)run{
    NSLog(@"人在跑");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Cat.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [Person new];
        [p run];
        
        Cat *cat = [Cat new];
        [cat run];
    }
    return 0;
}

9、类如果遵守协议后,实现了协议的方法,这些方法也可以被子类继承

示例,在上面例子的基础上,创建Person类的一个子类Student

Student.h

#import "Person.h"
@interface Student : Person
// 没有方法的声明
@end
Student.m
#import "Student.h"
@implementation Student
-(void)run{
    NSLog(@"Student run");
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Cat.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [Person new];
        [p run];
        
        Cat *cat = [Cat new];
        [cat run];
        
        Student *stu = [Student new];
        [stu run];
    }
    return 0;
}

(四)、protocol中@required和@optional

@required和@optional是协议方法声明中的两个关键字,它们主要用于控制方法是否要实现,用途在于方便程序员之间的交流

1、@required:这个方法必须要实现,若不实现,编译器会发出警告

2、@optional:这个方法不一定要是实现

代码示例,runProtocol.h

#import <Foundation/Foundation.h>
@protocol runProtocol <NSObject>
@required
-(void)run;

@optional
-(void)eat;
@end
注意:在protocol中,默认情况下,方法是必须必须要实现的

(五)、protocol与类型限制

设定情景:

某程序员A希望找一个会做饭、洗衣服的女生做女朋友,有国企工作的优先,满足条件的女生都可以给他发送消息

分析可知,要求如下

必需条件:

会做饭

会洗衣服

可选条件:

有份好工作

因此,有协议houseHold.h

#import <Foundation/Foundation.h>
@protocol houseHold <NSObject>
@required
-(void)ZuoFan;
-(void)XiYiFu;

@optional
-(void)goodJob;
@end

1、使用id存储对象时,对象的类型限制

格式:id <协议名称> 变量名

创建一个Girl类,并让Girl类遵守协议houseHold

Girl.h

#import <Foundation/Foundation.h>
#import "houseHold.h"
@interface <span style="font-family:Microsoft YaHei;">Girl</span> : NSObject<houseHold>
// 遵守houseHold协议
@end

Girl.m

#import "Girl.h"
@implementation Gril
// 实现houseHold协议中必须实现的方法
-(void)ZuoFan{
    NSLog(@"Girl 会做饭");
}
-(void)XiYiFu{
    NSLog(@"Girl 会洗衣服");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Girl.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Girl *mm = [Girl new];
        //增加<houseHold>以后,表示,obj只能赋值遵守了houseHold的对象
        id<houseHold> obj = mm;
    }
    return 0;
}

2、对象赋值时类型限制

格式:类名<协议名称> *变量名

main.m

#import <Foundation/Foundation.h>
#import "Girl.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
      Girl *mm = [Gril new];
        //表示,obj赋值的时候,必须是Girl对象,并且其遵守了houseHold协议
        Girl<houseHold> *obj = mm;
    }
    return 0;
}

3、对象关联关系下,对象的类型限制

假设,让女孩养一条狗,要求这个狗,必须会跑,那么代码如下

runProtocol.h

#import <Foundation/Foundation.h>
@protocol runProtocol <NSObject>
-(void)run;
@end

Dog.h

#import <Foundation/Foundation.h>
#import "runProtocol.h"
@interface Dog : NSObject<runProtocol>

@end

Dog.m

#import "Dog.h"
@implementation Dog
-(void)run{
    NSLog(@"狗在跑");
}
@end

Girl.h

#import <Foundation/Foundation.h>
#import "Dog.h"
#import "runProtocol.h"
@interface Girl : NSObject
//表示,女孩样的狗必须遵守runProtocol协议
@property (nonatomic,strong) Dog<runProtocol> *dog;
@end

main.m

#import <Foundation/Foundation.h>
#import "Girl.h"
#import "Dog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Dog *d = [Dog new];
        Girl *mm = [Girl new];
        Girl *obj = mm;
        //第三种类型限制,这里不能给obj.dog随意赋值
        obj.dog = d;
    }
    return 0;
}

(六)、protocol与代理模式

1、protocol代理设计模式引入

我们通过一个例子,初步理解什么是代理模式:婴儿需要吃和睡,但是他自己不会,所以要找一个保姆来帮他,因此这个保姆必须会喂婴儿吃饭和哄婴儿睡觉。下面是代码实现:

lookBabyProtocol.h

#import <Foundation/Foundation.h>
@class Baby;
@protocol lookBabyProtocol <NSObject>
// 要求保姆必须会做的
-(void)feedBabyEat:(Baby *)baby;
-(void)hongBabySleep:(Baby *)baby;
@end

BaoMu.h

#import <Foundation/Foundation.h>
#import "lookBabyProtocol.h"
@interface BaoMu : NSObject<lookBabyProtocol>
// 保姆遵守协议
@end

BaoMu.m

#import "BaoMu.h"
#import "Baby.h"
@implementation BaoMu
// 实现协议中的方法
-(void)feedBabyEat:(Baby *)baby{
    baby.blood += 20;
    NSLog(@"保姆正在喂婴儿吃东西,baby.blood = %.2f", baby.blood);
}
-(void)hongBabySleep:(Baby *)baby{
    baby.sleep +=10;
    NSLog(@"保姆正在哄婴儿睡觉,baby.sleep = %.2f",baby.sleep);
}
@end

Baby.h

#import <Foundation/Foundation.h>
@class BaoMu;
#import "lookBabyProtocol.h"
@interface Baby : NSObject
@property (nonatomic, assign) float blood;
@property (nonatomic, assign) float sleep;
@property(nonatomic,strong) BaoMu<lookBabyProtocol> *bm;
-(void)wantEat;
-(void)wantSleep;
@end

Baby.m

#import "Baby.h"
#import "BaoMu.h"
@implementation Baby
-(void)wantEat{
    NSLog(@"婴儿在哭...");
    [self.bm feedBabyEat:self];
}
-(void)wantSleep{
    NSLog(@"婴儿在哭...");
    [self.bm hongBabySleep:self];
}
@end
main.m
#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.blood = 30;
        baby.sleep = 20;
        
        baby.bm = baomu;
        
        [baby wantEat];
        [baby wantSleep];
        
        NSLog(@"%.2f,%.2f",baby.blood,baby.sleep);
    }
    return 0;
}

2、Protocol代理设计模式概念

代理设计模式:传入的对象,代替当前类完成了某个功能,成为代理模式

利用协议实现代理模式的主要思路为:

  • 定义一个协议,里面声明代理类需要实现的方法列表
  • 创建一个代理类,遵守上面的代理协议
  • 在需要代理的类中,定义一个对象,类型为id,且遵守代理协议 的成员变量(delegate)
  • 在需要代理的类中调用成员变量代理的方法,调用代理类的方法
  • main.m或其他使用需要代理的类的文件中,为需要代理的类的成员变量(代理类)赋值

3、Protocol代理设计模式应用场合

代理设计模式的场合:

  • 当对象A发生了一些行为,想告知B(让对象B成为对象A的代理对象)
  • 当对象B想监听对象A的一些行为(让对象B成为对象A 的代理对象)
  • 当对象A无法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A 的代理对象)
1)监听器的场合

2)通知的场合

3)有些事情,不想自己处理,想交给别人处理



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值