0
点赞
收藏
分享

微信扫一扫

iOS 中的协议 — @protocol

佳简诚锄 2021-09-30 阅读 64

1. 关于Protocol

在使用OC开发iOS程序的过程中经常会用到Protocol,定义一个Protocol的语法格式如下:

@protocol HumanProtocol <NSObject>

@required
- (void)name;
- (void)age;

//@optional
// ...

@end

iOS中协议的概念似于java中的接口interface,就是一堆方法的声明,但没有实现。一个类可以遵循一个或多个协议,任何类只要遵循了协议就相当于拥有了这个协议中所有的方法声明。Protocol可以定义在一个类的头文件上部,并直接应用在该类中(如作为delegate功能使用时),Protocol也可单独定义到一个类中,作为多个不同类来遵循并实现的interface。

//// .h文件
#import <Foundation/Foundation.h>

@protocol HumanProtocol <NSObject>

@required
- (void)name;
- (void)age;

//@optional
// ...

@end

@interface Tom : NSObject

@property (nonatomic, copy) id<HumanProtocol> delegate;

@end


//// .m文件
#import "Tom.h"

@interface Tom : NSObject <HumanProtocol>

@end

@implementation Tom

// 实现定义的方法
- (void)name {
}
- (void)age {
}

@end

或,将HumanProtocol写成一个独立的类文件,然后导入:

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

@interface Tom : NSObject <HumanProtocol>

@property (nonatomic, copy) id<HumanProtocol> delegate;

@end

@implementation Tom

// 调用协议变量,或实现协议方法

@end

2. 使用示例

<NSObject>是一个基协议,每个新协议都需要遵循。@protocol是定义一个协议的注解,其中,@required表示这个方法必须被实现,@optional表示这个方法不一定要被实现。

应用场景:
一个人需要一个Blog(Blog内容可以不同),这个Blog必须有通用的学习、分享等功能。则需求如下:

1、需要创建一个人和Blog;
2、需要创建一个Protocol来描述这些功能;
3、人拥有的Blog要实现这些功能;
4、Blog需要遵循这个Protocol且实现它。

#import <Foundation/Foundation.h>

@protocol BlogProtocol <NSObject>
- (void)study;
- (void)share;
@end

----------------------------

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

@class Blog;
@interface Person : NSObject
//拥有的Blog要实现Protocol的功能
@property (nonatomic,strong) Blog<BlogProtocol> *blog;
@end

----------------------------

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

@interface Blog : NSObject<BlogProtocol>
@end

#import "Blog.h"
@implementation Blog
- (void)study {
    NSLog(@"%s",__func__);
}
- (void)share {
    NSLog(@"%s",__func__);
}
@end

----------------------------

Person *p = [[Person alloc] init];
Blog *blog = [[Blog alloc] init];
// 此处会判断Blog是否符合协议的Blog,否则报警告
p.blog = blog;

//判断Blog是否有实现协议内容
if ([p.blog respondsToSelector:@selector(study)]) {
    [p.blog study];
}
if ([p.blog respondsToSelector:@selector(share)]) {
    [p.blog share];
}

3. 需要注意的几个点

协议与继承的区别:继承之后默认就有实现,而协议只要声明没有实现;相同类型的类可以使用继承,但是不同类型的类只能使用协议;协议可以用于存储方法声明,可以将多个类中共有的方法抽取出来,以后让这些类遵守协议即可

协议与 Category 的区别:category是针对类进行扩展,而且该类必须有里面的所有成员,协议不同可以选择性实现;category是针对一个具体的类实现,其他类没有,协议允许任何类使用并实现;Category由本身实现,不允许其他类重写,协议只定义方法,无具体实现任何类允许自己实现;category被单继承的特性所限制,协议则没有继承限制。

//// Protocol类
@protocol SportProtocol <NSObject>
@property (nonatomic,copy) NSString *sportType;
- (void)playFootball;
- (void)playBasketball;
- (void)run;
@end

//// 实现类:Person
#import <Foundation/Foundation.h>
#import "SportProtocol.h"

@interface Person : NSObject<SportProtocol>
@end

#import "Person.h"
@implementation Person
@synthesize sportType=_sportType;

- (void)readSportType{
   NSLog(@"%@",_sportType);
}
@end

// Person *p =[[Person alloc]init];
// p.sportType = @"sport";
// [p readSportType];

上面方法中用到了@synthesize sportType=_sportType,sportType 属性为 _sportType 成员变量合成访问器方法。

//// 继承类:Student
#import "Person.h"
@interface Student : Person
@end

// Student *stu = [[Student alloc]init];
// [stu playBasketball];

一个类可以遵守多个protocol,protocol又可以遵守其他protocol:

//// 遵守多个protocol
#import <Foundation/Foundation.h>
#import "SportProtocol.h"
#import "StudyProtocol.h"

@interface Person : NSObject<SportProtocol, StudyProtocol>
@end

//// protocol遵守其他protocol
#import <Foundation/Foundation.h>
#import "BaseProtocol.h"

@protocol StudyProtocol <BaseProtocol>
- (void)studyEnglish;
- (void)studyChinese;
@end
举报

相关推荐

0 条评论