Objective - C基础: 第六天 - 5.protocol协议的基本认识

学到现在, 我们很快就要结束OC的教程了, 讲完protocol, OC语法就全部学完了, 现在我们来看看什么protocol, 在OC中, 我们都知道要.h文件里是用来声明方法和成员变量, .m文件里是用来实现的, 也知道类别是给系统类扩充一些必要的方法, 那么有没有一种机制是用来给我们自定义的类声明方法的呢? 其实是有的, 那就是protocol, 也就是协议, 下面让我们一起来看看:


例子:

#import <Foundation/Foundation.h>

@interface Person : NSObject

- (void)test;

@end

@implementation Person

- (void)test
{
    NSLog(@"我是test方法.");
}
@end

这个就是我们以前所运用的方法声明, 但这样子的声明方式就只能在一个类里面使用, 如果另一个类也要使用, 就必须拷贝一份过来, 重新声明, 重新实现, 但protocol出现之后, 这样子的问题就不存在了, 下面让我们来继续看看:



#import <Foundation/Foundation.h>

@protocol MyProtocol

- (void)test;

@end

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

@interface Person : NSObject <MyProtocol>

@end

@implementation Person

- (void)test
{
    NSLog(@"我是test方法.");
}

@end

在这之前, 我们都知道冒号" : "是用在继承, 那么尖括号" <> "就是用在协议, 只要声明一个协议, 无论多少个类要用, 也不需要拷贝, 直接遵守这个协议, 那么就可以拥有协议里所有的方法.

PS: 父类遵守了协议, 子类一样也可以使用, 原理和继承类似.



那么protocol里有什么需要注意的呢?

例子:



为什么在Person.m文件里面会出现警告呢? 其实这个和Protocol的机制有关, 在Protocol中有两种方法声明, 一种是@required, 另一种是@optional, 直接翻译我们也知道第一个是必须的, 第二个是可选的, 而在Protocol声明的方法里, 默认就是required, 也就是必须实现的, 一旦遵守了协议的类, 没有实现必须的方法时, 那么编译器就会报警告.



那么问题来了, 既然默认都是required, 那么干嘛还要写这个?? 不是蛋疼没事做么? 其实是有一定的道理的, 这个写出来并不是给编译器看的, 是用来给我们程序员之间交流的, 当你的合作伙伴看到了这个之后, 他就知道, 原来这个方法一定要我去实现, 那么他就会去实现这个方法, 你不写的的话, 那他就会跑过来问你, 这个我需不需要实现啊, 哪个是可选的啊, 等等一系列额问题~~大家都懂的~~





我们都知道OC是单继承的, 不可以继承多个类, 那么协议呢? 其实协议是可以多个遵守的, 比如:





其实协议一般是使用在设计模式场景, 比如代理模式, 观察者模式等等, 这个我们后面会慢慢讲~~





其实协议还有一种, 叫做基协议, 在我们之前学习过一个东西叫做基类NSObject, 就是所有类都继承于它, 所以叫做基类, 而在协议中也有一个基协议, 它的名字也叫做NSObject, 而所有的协议也必须遵守它, 比如:





既然有基协议这个原理, 那么我们是不是可以猜想一下, 一个自定义的协议是否可以遵守另一个自定义的协议呢? 其实是可以的, 比如:




MyProtocol2遵守了MyProtocol协议, 而Person又遵守了MyProtocol2协议, 那么在Person里就不用遵守它了, 直接遵守MyProtocol2就可以拿到MyProtocol的方法, 并且实现, 和子父类继承关系有些相似.

PS: 因为MyProtocol遵守了基协议, 而MyProtocol2又遵守了MyProtocol, 所以MyProtocol2就不需要遵守基协议.



在某些情况, 我想让系统类遵守我自定义的协议怎么办? 比如:



我想让obj这个对象遵守我自定义的协议, 但是NSObject这个类是不可能遵守我自定义的协议的, 那么如何解决?? 其实很简单, 继续往下看:



解决办法就像上面的obj2obj3一样, 但obj3出现一个问题, 因为NSObject这个基类是不可能遵守我们自定义的协议的, 所以会报警告, 说类型不匹配, 而obj2使用的是Person, 所以类型匹配成功, 只显示了该对象并没有使用, 和obj一样.



使用Protocol是有一个书写规范的, 这个规范和声明类是一样的, 下面我们来看看:


Person.h文件中只用@protocol声明有该协议, 直到真正要去使用的时候才在.m文件里面引用, 这可以保证我们app的性能.




对了, 其实属性也可以遵守协议的, 比如:





总结:

 1.协议的定义

 @protocol 协议名称 <NSObject>

  // 方法声明列表....

 @end


 2.如何遵守协议

 1> 类遵守协议

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

 @end

 

 2> 协议遵守协议

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

 @end

 

 3.协议中方法声明的关键字

 1> @required (默认)

   要求实现,如果没有实现,会发出警告

 

 2> @optional

   不要求实现,怎样不会有警告

 

 4.定义一个变量的时候,限制这个变量保存的对象遵守某个协议

 类名<协议名称> *变量名;

 id<协议名称> 变量名;

 例子:

 NSObject<MyProtocol> *obj;

 id<MyProtocol> obj2;

 

 如果没有遵守对应的协议,编译器会警告

 

 5.@property中声明的属性也可用做一个遵守协议的限制

 @property (nonatomic, strong) 类名<协议名称> *属性名;

 @property (nonatomic, strong) id<协议名称> 属性名;

 例子:

 @property (nonatomic, strong) Dog<MyProtocol> *dog;

 @property (nonatomic, strong) id<MyProtocol> dog2;




再补充一点:

 1.协议可用定义在单独.h文件中,也可用定义在某个类中

 1> 如果这个协议只用在某个类中,应该把协议定义在该类中

 2> 如果这个协议用在很多类中,就应该定义在单独文件中

 

 2.分类可用定义在单独.h.m文件中,也可用定义在原来类中

 1> 一般情况下,都是定义在单独文件

 2> 定义在原来类中的分类,只要求能看懂语法




好了, OC语法到此告一段落了, 谢谢大家的观看~~

posted @ 2015-01-29 21:54  背着吉他去流浪  阅读(267)  评论(0编辑  收藏  举报