类别 和 协议

一 、类别 (Category):

(一)适用场景:在不能查看类源文件的情况下向类中添加私有方法。

(二)使用方式:

1.创建:

(注意事项:类别名称必须唯一。)

2.声明:

@interface 原类名 (扩展的类别名).

@property (retain,nonatomic)   属性1;//属性必须是@dynamic类型。

@property (retain,nonatomic)   属性2;

/*类别的方法都有可实现与不可实现两种属性*/

@required;//必须实现的方法。

-(返回值)方法一;

@optional;//可选实现的方法。

-(返回值)方法二;

@end

(注意事项:类别中不可以添加实例变量,但是可以添加属性,只是属性必须是@dynamic类型。)

3.实现:

4.调用:当前类的任意对象都可以调用这些方法。

(三)注意细节:

1.类别可以访问其继承类的实例变量,而且类别方法的优先级要高于其继承类方法的优先级。

(四)优缺点:

缺点:

1.无法定义实例变量,因为类别只是给已有类添加方法,所以并不开辟空间。

2.类别方法名称要保证不能跟现有类中的方法重名,因为类别方法的优先级高于所属类方法的优先级,当两者重名的时候,原方法无效。

优点:

1.可以将类别的实现分散于多个不同的文件中或者框架中

2.创建对私有方法的前向引用。

3.以及向对象添加非正式协议。

二、延展 (Extension)

延展其实就是类别的一种特殊情况,对类别做的延伸。

(一)适用场景:适用于可以常看类源文件的情况,可以直接在源文件中添加方法和实例变量或属性。

(二)特点:

1.不需要起名字,直接在类的实现文件中添加。

2.可以添加实例变量。

3.可以修改当前类属性的特性。

例如:@property (readonly,assign) NSInteger thing;//原有类的属性

@property (readwrite,assign) NSInteger thing;//延展的属性,编译器会自动给这个属性添加setter方法。

(三)使用方式:

@interface 当前类名 ()

{

实例变量1;//这里的实例变量都是私有的(@private),并不是默认的受保护的(@protected)。所以,只能当前类访问。

实例变量2;

}

@property (readonly,assign) NSInteger thing1;

三、协议 (Protocol)

(一)适用场景:

(二)使用:

1.声明:

@protocol 协议名 <父类协议>  /*协议名称也必须是唯一的*/

{

实例变量1;

实例变量2;

}

在类的声明中引入协议

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

方法一;

方法二;

@end

2.实现:需要遵守某个协议的类去实现协议中的方法。

(三)、协议和数据类型

可以为实例变量和函数参数中的数据类型指定需要遵循的协议。表示该类型的对象必须遵循某个协议。

例如:

@property (retain,monatomic) id<协议名>对象指针;

-(返回值类型)方法名:(参数类型<协议名>)形参;

注意:可以通过一个方法来判断代理是否实现了某个方法,可以使用“[self.delegate respondsToSelector:(SEL)]”这个方法返回值是BOOl类型,所以可以通过添加到if语句中来防止因为代理没有实现某个方法而崩溃。

使用delegate的步骤

第一步:先搞清楚谁是谁的代理

第二步:定义代理协议,协议名称的命名规范: 控件类名 + Delegate  。

第三步:定义代理方法

代理方法一般都是定义为@optional

代理方法名一般都是以控件名开头

代理方法至少有一个参数,将控件本身传过去

第四步:设置代理(delegate)对象 比如:myView.delegate = xxxx;

第五步:代理对象签署协议

第六步:代理对象实现协议中应该实现的方法。

你可能感兴趣的:(类别 和 协议)