Protocol基础知识及应用

本文介绍了Objective-C中的协议基本概念,包括非正式协议的定义与采纳,关键字@required和@optional的使用,以及协议遵守协议的实现。通过实例讲解了代理设计模式的应用,以婴儿和保姆的关系为例,展示了如何创建协议、婴儿类和保姆类,并让保姆类遵循协议以完成特定任务。最后,还探讨了代理模式在找房场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.非正式协议概念
给NSObject或者NSObject的子类增加类别
2. 1)定义协议 (.h文件中)
2)采纳(采用)协议(ClassA.h中,类声明的时候采纳协议)
3)ClassA.m中 实现协议对应的方法

协议定义

@protocol协议名称 <NSObject> //默认遵守NSObject协议

采纳协议
一.类遵守协议(创建类的时候遵守某个或几个协议)

@interface类名:父类<协议名称>
@end

@interface类名:父类<协议名称1,协议名称2>
@end

二、协议遵守协议(一个协议可以遵守其他多个协议)

@protocol 协议名称<其他协议名称>
@end

@protocol 协议名称<其他协议名称1,其他协议名称2>
@end

2.baseProtocol.h中定义协议

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

//新建Person.h文件
#import"baseProtocol.h"
#import"workProtocol.h"
// 遵守协议
// 实现方法
// 当我们遵守了某个协议后,就相当于这个类有了协议中所有的 方法的声明
@interface Person:NSObject <baseProtocol,workProtocol>
@end
//Person.m文件
#import"Person.h"
@implement Person
- (void)eat{
}
- (void)run{
}

- (void)work{
} 
@end
// 新建.m文件
#import"Person.h" //导入Person文件
Person *p = [Person new];
[p eat];
[p run];
[p work];  

协议的关键字 @required / @optional

@protocol RunProtocol <NSObject>
// @required 修饰的必须要实现的方法
@required
- (void)run;

// @optional 修饰可以选择实现的方法
@optional
- (void)eat;
@end;
  1. protocol类型限制
    id / instancetype 不同用法

houseHold.h

#import <Foundation/Foundation.h>
@protocol houseHold <NSObject>
@required;  // 可省略
- (void)ZuoFan;
- (void)XiYiFu;
@optional;
- (void)goodJob;
@end;

main.m

#import "houseHold.h"
#import "Dog.h" // Dog类
#import "Girl.h"
Dog *d = [Dog new];
Girl *mm = [Girl new];
NSString *str = @"";
// 增加类型限制
// 第一种类型限制:给id类型增加限制
// id<houseHold> obj;
// 增加<houseHold>以后,表示obj只能赋值遵守了houseHold协议的对象
// id类型可以赋给任何值id obj = str id obj = d;

id <houseHold> obj = d; 
//警告 obj没有实现对应的houseHold协议
//在d所在的Dog.h中导入头文件#import"houseHold.h"
  遵守<houseHold>协议
// 修改后赋值语句为
id <houseHold> obj = d;

Dog.h 修改后

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

Girl.h

#import "Foundation/Foundation.h"
#import "houseHold.h"
@interface Girl: NSObject <houseHold> 
@end
.m文件
// 第二种类型限制
// 表示,obj2赋值的时候,必须是Girl对象,并且遵守了houseHold协议
Girl<houseHold> *obj2 = mm;

第三种类型
新建caculatorProtocol协议 caculatorProtocol.h

#import <Foundation/Foundation.h>
@protocol caculatorProtocol
- (void)mod;
@end;

Girl.h

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

// 女孩养一条狗
// 要求这条狗,必须会算数
@property (nonatomic,strong) Dog<caculator> *dog;
@end

// main.m 文件中 第三种类型限制
Dog *d = [Dog new];
Girl *mm = [Girl new];
Girl<houseHold> *obj2 = mm;
obj2.dog = d;

Dog.h中添加遵守caculatorProtocol协议

#import <Foundation/Foundation.h>
#import "caculatorProtocol.h"
@interface Dog: NSObject<caculatorProtocol>
@end
  1. id类型和instancetype的区别
    1)instancetype只能作为函数或者方法的返回值
    2)id能作为方法或者函数的返回值、参数类型、也用来定义变量
    3)instancetype的好处

    • 能精确地限制返回值的具体类型
  2. protocol代理设计模式引入
    举例说明:婴儿和保姆之间有个协议,协议中写明保姆需要做什么事情,保姆遵守该协议,于是保姆就需要实现该协议中的条款成为代理人。婴儿饿了困了需要保姆照顾,使用类实现当前功能。
    第一步,制定协议
    照顾小孩的协议 (lookBabyProtocol)
    - 喂奶 (feedBabyEat)
    - 哄睡(HongBabySleep)
    第二步,创建相关的类
    1) 婴儿类
    类名:Baby
    属性:保姆、体力值、睡眠值
    行为:
    想吃东西(wantToEat) - 保姆喂奶
    想睡觉(wantToSleep) - 保姆哄他睡觉
    2) 保姆类 (需要遵守协议)
    类名: Baomu
    行为

lookBabyProtocol.h

#import  <Foundation/Foundation.h>
@protocol lookBabyProtocol <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat;
// 哄婴儿睡觉
- (void)hongBabySleep;
@end

Baby.h

#import <Foundation/Foundation.h>

@class BaoMu;
#import "lookBabyProtocol"
@interface Baby : NSObject
// 保姆、体力值、睡眠值
@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];
}
- (void)wantSleep{
      NSLog(@"婴儿在哭");
      // 保姆要哄婴儿睡觉
      [self.bm HongBabySleep];
}
@end

BaoMu.h

#import <Foundation/Foundation.h>
//保姆想成为baby的代理人,就必须遵守lookBabyProtocol协议
#import "lookBabyProtocol.h"

@interface BaoMu : NSObject <lookBabyProtocol>

@end

BaoMu.m

#import "BaoMu.h"
@implementation BaoMu
- (void) feedBabyEat{
     NSLog(@"保姆正在喂婴儿吃东西");
}
- (void)HongBabySleep{
     NSLog(@"保姆正在哄婴儿睡觉");
}
@end

main.m 文件

#import <Foundation/Foundation.h>
#import "BaoMu.h"
#import "Baby.h"
{
   BaoMu *baomu = [BaoMu new];
   Baby *baby = [Baby new];
   baby.bm = baomu;

   [baby wantEat];
   [baby wantSleep];
}

为了体现出实现了协议功能将协议修改为
lookBabyProtocol.h

#import  <Foundation/Foundation.h>
#import <Baby.h>
@protocol lookBabyProtocol <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat : (Baby *)baby;
// 哄婴儿睡觉
- (void)hongBabySleep : (Baby *)baby;
@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

Baby.h

#import <Foundation/Foundation.h>

@class BaoMu;
#import "lookBabyProtocol"
@interface Baby : NSObject
@property (nonatomic, assign) float weight; //新增
@property (nonatomic, assign) float sleep;
// 保姆、体力值、睡眠值
@property (nonatomic, strong) BaoMu <lookBabyProtocol> *bm;
- (void)wantEat;
- (void)wantSleep;
@end

lookBabyProtocol.h

#import <Foundation/Foundation.h>
 //替换导入Baby.h
@class Baby;  
@protocol lookBabyProtocol : <NSObject>
// 喂婴儿吃饭
- (void)feedBabyEat : (Baby *)baby;
// 哄婴儿睡觉
- (void)HongBabySleep : (Baby *)baby;

BaoMu.m

#import "BaoMu.h"
#import "Baby.h"

@implementation BaoMu
- (void)feedBabyEat : (Baby *)baby {
   baby.weight += 1;
   NSLog(@"保姆正在喂婴儿吃东西,baby.weight = %.2f", baby.weight);
}
- (void)HongBabySleep : (Baby *)baby {
  baby.sleep += 10;
   NSLog(@"保姆正在哄婴儿睡觉, baby.sleep = %.2f", baby.sleep);
}
@end

main.m 文件

#import <Foundation/Foundation.h>
#import "BaoMu.h"
#import "Baby.h"
{
   BaoMu *baomu = [BaoMu new];
   Baby *baby = [Baby new];
   baby.weight = 10;
   baby.sleep = 20;

   baby.bm = baomu;

   [baby wantEat];
   [baby wantSleep];

   NSLog(@"%.2f ,%.2f ",baby.weight, baby.sleep);
}

6.应用:通过中介找房子
Student.h

#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"

@interface Student : NSObject
- (void)needHouse;
@property (nonatomic, strong) id <findHouseProtocol> delegate;
@end

Student.m

#import <Student.h>

@implementation Student
- (void)needHouse {
     NSLog(@"学生需要一个温暖的家");
     [self.delegate findHouse];
}

findHouseProtocol.h

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

LinkHome.h 创建代理链接

#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"
// 采纳协议
@interface LinkHome : NSObject <findHouseProtocol>
@end

LinkHome.m

#import "LinkHome.h"

@implementation LinkHome
- (void)findHouse {
NSLog(@"链家地产正在帮学生找房子");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Student"
#import "LinkHome.h"

Student *stu = [Student new];
// 代理的类
LinkHome *linkHome = [LinkHome new];
stu.delegate = linkHome;
[stu needHouse];

// 代理类 LinkHome
// 代理对象 delega
// 协议 findHouseProtocol
// 协议内容 findHouse

WAWJ.h 新建代理类

#import <Foundation/Foundation.h>
#import "findHouseProtocol.h"

@interface : NSObject <findHouseProtocol>
@end

WAWJ.m

#import "WAWJ.h"

@implementation WAWJ
- (void)findHouse {
 NSLog(@"我爱我家正在找房子");
}
@end

main.m

#import <Foundation/Foundation.h>
#import "Student"
#import "LinkHome.h"

Student *stu = [Student new];
// 代理的类
LinkHome *linkHome = [LinkHome new];
WAWJ *wj = [WAWJ new];

stu.delegate = wj;
[stu needHouse];

代理模式概念
传入的对象,代替当前类完成了某个功能,成为代理模式
利用协议实现代理模式的主要思路为:
1.定义一个协议,里面声明代理类需要实现的方法列表,比如这里一个代理类需要实现的feedBaby 和 hongBabySleep方法
2.创建一个代理类(比如BaoMu),遵守上面的代理协议
3.在需要代理的类中(Baby),定义一个对象 类型为id 且遵守代理协议的成员变量(delegate)
4.在Baby类中调用成员变量delegate(代理)的方法,调用代理类的方法
5.main.m或其他使用Baby类的文件中,为Baby类的成员变量(代理类)赋值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值