概述
协议,protocol,是一种特殊的interface,这种特殊的interface不允许定义数据成员,允许声明Method,protocol纯粹作为接口使用,因此没有对应implementation
- protocol不允许定义数据成员
- protocol允许声明Method,包括instance method(-)和class method(+),protocol没有对应implementation
- protocol可继承protocol,而且支持多继承,protocol继承本质是union父protocol的Method声明到子protocol中
- protocol纯粹作为接口使用,因此没有实体,不能实例化
- protocol的Method声明允许的修饰词包括@required和@optional,默认@required,@required是必须实现接口,@optional是可选实现接口
- @required和@optional的唯一区别是对应接口没有实现时编译是否warning(@required编译warning,@optional编译不warning)
protocol
@interface FBFood : NSObject
@end
@implementation FBFood
@end
@protocol FBFeedFood1
- (void)feedRice:(int)rice andMeat:(int)meat;
- (void)feedFruit:(int)fruit andFish:(int)fish;
@end
@protocol FBFeedFood2
- (void)feedRice:(int)rice andMeat:(FBFood *)meat;
- (void)feedFruit:(int)fruit andFish:(FBFood *)fish;
@end
@protocol FBFeedFood <FBFeedFood1, FBFeedFood2>
- (void)feedFruit:(FBFood *)fruit andFish:(FBFood *)fish;
@optional
- (void)feed;
@end
@interface FBAnimal : NSObject <FBFeedFood>
@end
@implementation FBAnimal
- (void)feedRice:(int)rice andMeat:(int)meat
{
NSLog(@"feedRice:andMeat:");
}
- (void)feedFruit:(FBFood *)fruit andFish:(FBFood *)fish
{
NSLog(@"feedFruit:andFish:");
}
@end
总结:
- protocol可继承protocol,而且支持多继承,protocol继承本质是union父protocol的Method声明到子protocol中,因此不可避免的会与已有Method声明相同(SEL相同),重复的Method声明的参数列表可能会不同,union时选取重复Method声明的优先级为:FBFeedFood->FBFeedFood1->FBFeedFood2(即@protocol FBFeedFood <FBFeedFood1, FBFeedFood2>的protocol定义顺序)
应用
@protocol FBFeedFood1
- (void)feedRice:(int)rice andMeat:(int)meat;
@end
@protocol FBFeedFood2
- (void)feedFruit:(int)fruit andFish:(int)fish;
@end
@protocol FBFeedFood <FBFeedFood1, FBFeedFood2>
@end
@protocol FBGuard
@required
- (void)watch;
@optional
- (void)attack;
@end
@interface FBAnimal : NSObject <FBFeedFood>
{
@public
int _food;
}
@end
@implementation FBAnimal
- (void)feedRice:(int)rice andMeat:(int)meat
{
NSLog(@"feedRice:andMeat:");
}
- (void)feedFruit:(int)fruit andFish:(int)fish
{
NSLog(@"feedFruit:andFish:");
}
@end
@interface FBDog : FBAnimal <FBGuard>
{
@public
int _vol;
}
- (void)bark;
@end
@implementation FBDog
- (void)bark
{
NSLog(@"bark");
}
- (void)watch
{
NSLog(@"watch");
}
@end
- (void)use_protocol
{
NSObject<FBFeedFood> *animal1 = [[FBAnimal alloc] init];
//animal1->_food = 5;
[animal1 feedRice:5 andMeat:8];
[animal1 methodForSelector:@selector(feedFruit:andFish:)];
//[animal1 unknownMethod];
id<FBFeedFood> animal2 = [[FBAnimal alloc] init];
//animal2->_food = 5;
[animal2 feedFruit:5 andFish:8];
//[animal2 methodForSelector:@selector(feedFruit:andFish:)];
//[animal2 unknownMethod];
id<FBGuard> animal3 = [[FBDog alloc] init];
//animal3->_vol = 8;
//[animal3 feedRice:5 andMeat:8];
//[animal3 methodForSelector:@selector(feedFruit:andFish:)];
[animal3 watch];
FBAnimal<FBFeedFood> *animal4 = [[FBAnimal alloc] init];
animal4->_food = 5;
[animal4 feedRice:5 andMeat:8];
[animal4 feedFruit:5 andFish:8];
FBDog<FBGuard> *animal5 = [[FBDog alloc] init];
//animal4->_vol = 8;
[animal5 bark];
[animal5 watch];
NSLog(@"FBAnimal confirm FBFeedFood1 = %d", [FBAnimal conformsToProtocol:@protocol(FBFeedFood1)]);
NSLog(@"FBAnimal confirm FBFeedFood = %d", [FBAnimal conformsToProtocol:@protocol(FBFeedFood)]);
NSLog(@"FBAnimal confirm FBGuard = %d", [FBAnimal conformsToProtocol:@protocol(FBGuard)]);
NSLog(@"FBDog confirm FBFeedFood1 = %d", [FBDog conformsToProtocol:@protocol(FBFeedFood1)]);
NSLog(@"FBDog confirm FBFeedFood = %d", [FBDog conformsToProtocol:@protocol(FBFeedFood)]);
NSLog(@"FBDog confirm FBGuard = %d", [FBDog conformsToProtocol:@protocol(FBGuard)]);
}
output:
feedRice:andMeat:
feedFruit:andFish:
watch
feedRice:andMeat:
feedFruit:andFish:
bark
watch
FBAnimal confirm FBFeedFood1 = 1
FBAnimal confirm FBFeedFood = 1
FBAnimal confirm FBGuard = 0
FBDog confirm FBFeedFood1 = 1
FBDog confirm FBFeedFood = 1
FBDog confirm FBGuard = 1
使用protocol两种方式:
- 类<protocol1, protocol2...> *对象名
- id<protocol1, protocol2...> 对象名
总结:
- 类<protocol1, protocol2...> *允许访问类+协议的成员,id<protocol1, protocol2...>只允许访问协议的成员,否则编译warning
- 习惯使用id<protocol1, protocol2...>定义实例对象,简洁明了,因为使用protocol一般只关注protocol的Method接口(不大使用类提供的功能)
- 类遵守协议并不确保类实现了协议的所有Method(@required不实现,编译warning,@optional不实现,编译不warning)
- 父类遵守的protocol,子类继承遵守