在重温《OBJC编程基础》这本书时,对于非正式协议的感觉非常陌生,阅读了一篇王中周的博客,结合自己在书中阅读的内容,做一些总结。

 

一、非正式协议

  显然这个名词是相对于正式协议而言的。在解释非正式协议之前,先引用两段话:

 1、在《Cocoa设计模式》第六章类别的6.3.2把类别用于非正式协议一节中,这样写到:

   非正式协议通常定义为NSObject的类别。类别接口中指定的方法可能会或者可能不会被框架类实际地实现。非正式协议位于一种设计灰区中。正式协议由编译器检查并且代表一种关于对象能力的保证,但是非正式协议不会做出保证----而只会给出提示

  -----摘自王中周博客 原地址:http://blog.csdn.net/wzzvictory/article/details/9295317

 

  可以看出,所谓的非正式协议不过就是NSObject的类别。所以其所有的子类都含蓄的接受了这个协议。而且要注意:非正式协议内的方法都是可选实现的。因此,在调用协议内的方式时,需要先检查对象是否实现了该方法。而且非正式协议是Foundation和AppKit类实现委托的唯一方式。

 

  匿名类别(类拓展):

@interface ViewController (){// 匿名类别----类拓展
    float scH;// 增加实例变量
}

- (void)setValue:(id)value forKey:(NSString *)key;// 增加方法

@property (nonatomic, strong) NSString *name;// 增加属性

@end

这种写法的类别叫匿名类别,又叫类扩展,所谓的扩展,其实就是为一个类添加额外的原来没有的变量、方法或者合成属性。

 

  类别:

@interface NSString (theNew)// 类别

@property (nonatomic, strong) NSString *name;

- (void)setValue:(id)value forKey:(NSString *)key;


@end

这种写法是类别,只能增加方法和属性,但是不能增加实例变量。

 

那么类别与匿名类别有什么区别呢?

①类别中只能增加方法;

②是的,你没看错,类扩展不仅可以增加方法,还可以增加实例变量(或者合成属性),只是该实例变量默认是@private类型的(作用范围只能在自身类,而不是子类或其他地方);

③类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。

④类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。

⑤定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。

 

二:正式协议:

  1.概念

  与非正式协议一样,正式协议是包含了方法和属性的有名称列表,但与非正式协议不同的是正式协议要要求显式地采用。采用(adopt---私以为翻译为接受更好)协议的办法是在类@interface声明中列出协议的名称。采用协议后,你的类就要遵守该协议。采用协议就意味着你承诺实现改写的所有方法(应当是@required的方法)。

 ----摘自《OBJC编程基础》

 2.正式协议存在的意义

  从字面上理解,正式协议比非正式协议要正式了很多,它存在的意义在于:

  正式协议可以将业务中的方法定义剥离出来,形成一个单独的文件,这跟传统OO中的提取接口是不谋而合的。如果遇到二个系统需要交换数据,可以制定一套双方都遵守的协议,然后这二个系统中都把这个协议文件添加到项目中,实现它即可。

  3、继承性

  正式协议和类一样,是可以继承的,书写格式同类继承相似:

  

@protocol NewProtocol <NSCopying>
- (void)setName:(NSString *)name;
@end