———-android培训、Java培训、iOS培训,期待与您交流———-
Category
一、基本概念
分类的作用:
- 在不修改原有的类的基础上增加新的方法
- 一个庞大的类可以分模块开发,便于维护
- 一个庞大的类可以由多个人来编写,更有利于团队合作
使用类别的目的
- 对现有类进行扩展:对自定义的类甚至是框架中的类进行扩展,从而实现项目特殊需求。
- 作为子类的替代手段:不需要定义和使用一个子类,可以通过类别直接向已有的类中增加方法。
- 对类中的方法归类:利用category把一个庞大的类划分为小块来分别进行开发,从而更好的对类中的方法进行更新和维护。
关于非正式协议
为NSObject添加的分类就称作非正式协议。非正式协议一般不需要进行实现,而是在子类中进行方法的重写。
二、分类的使用
1.分类的实现步骤
声明
格式:
@interface 待扩展的类名 (分类的名称)
@end
实现
格式:
@implementation 待扩展的类名 (分类的名称)
@end
文件的命名格式:
待扩展的类名+分类名称
使用
与使用类中原有的方法一样,用方括号调用。
2.代码举例
假设现在已经有Person类,要创建一个Person的类扩展,首先在当前target中新建Objective-C File,文件名填写分类名称,File Type选择Category,类名填写要扩展的类名。文件创建好之后,就像使用普通类一样,在.h文件中声明方法,在.m文件中实现方法。例如:
/******Person+play.h*******/
#import "Person.h"
@interface Person (play)
-(void)paly;
@end
/******Person+play.m*******/
#import "Person+play.h"
@implementation Person (play)
-(void)paly{
NSLog(@"playing");
}
@end
这样在使用Personm类时就可以直接调用play方法了。
但是Category也有他的局限:
- 不能在Category中扩展类的成员变量
- 名称冲突,当Category中实现的类与已有方法重名时,会完全取代已有方法。
三、类扩展(延展)
1.类扩展的作用
分类(Category)的一个缺陷是只能扩展方法而不能扩展成员变量,类扩展(Class Extension)可以实现向原有类中添加成员变量。
2.实现方法
类扩展实际上是一个特殊的分类,在定义@interface的时候不对分类进行命名,这个分类就成了一个类扩展。创建类扩展的时候在新建文件时File Type选择Extension即可。例如:
/******Person_body.h*******/
#import "Person.h"
@interface Person ()
{
float _weight;
float _height;
}
@end
3.注意
- 类扩展只有@interface部分而没有@implementation
- 类扩展也可以添加方法,但是方法的实现要写在类的.m文件中
- 可以改变变量的读写权限
Protocol
一、基本概念
1.Protocol的作用
Protocol(协议)是包含了方法和属性的有名称列表。采用协议的类必须实现协议要求实现的方法,否则编译器会报错。
2.协议的使用流程
定义协议(在.h文件中)
在当前target中新建Objective-C文件,File Type选择Protocol。
格式:
@protocol 协议名称 <NSObject> //默认遵守NSObject协议 //方法声明列表 @end;
采用(遵守)协议
类遵守协议
创建类的时候遵守某个或者某几个协议
@interface 类名 : 父类 <协议名称1,协议名称2> @end
协议遵守协议
协议也可以遵守一个或多个其他协议
@protocol 协议名称 <其他协议名称1,其他协议名称2> @end
实现协议要求实现的方法
3.协议的注意事项
- Protocol:就一个用途,用来声明方法(不能声明成员变量),不能写实现。
- 只要某个类遵守了这个协议,就拥有了这个协议中的所有方法声明。
- 只要父类遵守了某个协议,那么子类也遵守。
- Protocol声明的方法可以让任何类去实现
- OC不能继承多个类(单继承)但是能够遵守多个协议。
- 基协议:\
4.可选和必须
在协议中,可以定义一个方法的声明是否必须被实现,通过关键字@optional和@required实现,例如:
@protocol 协议名称 <NSObject>
@optional
-(void)run;//可选实现,不是必须的
@required
-(void)eat;//必须实现
@end;
默认是@required。
5.类型限制
当创建一个对象时,希望这个对象必须遵守了指定的协议,就需要使用类型限制。
对象赋值时的类型限制
格式:
类名<协议名称> *变量名
例如:
Person<run> *p = [Person new];//只有Person类确实遵守了run协议编译器才不会报错
关联关系下的类型限制
使用@property声明成员变量时,如果成员变量是一个对象,则可以使用类型限制对对象进行限制,格式如下:
@property 类名<协议名> *变量名;
例如:
@property Pet<dog> *pet;//只有遵守了dog协议的Pet类才能作为该类的成员变量
使用id存储对象时的类型限制
格式:
id <协议名称> 变量名
例如:
id<run> p = [Person new]
二、代码实现
/******studyProtocol.h******/
@protocol studyProtocol <NSObject>
-(void)studyOC;
@end
/******playProtocol.h******/
@protocol playProtocol <NSObject>
-(void)playPCgame;
@optional
-(void)playBasket;
@end
/******Person.h******/
#import <Foundation/Foundation.h>
#import "playProtocol.h"
@interface Person : NSObject<playProtocol>
@end
/******Person.m******/
#import "Person.h"
@implementation Person
-(void)playPCgame{
NSLog(@"Playing PC game now");
}
@end
/******Student.h******/
#import "Person.h"
#import "studyProtocol.h"
@interface Student : Person<studyProtocol>
@end
/******Student.m******/
#import "Student.h"
@implementation Student
-(void)studyOC{
NSLog(@"Studying OC now");
}
@end
/******main.m******/
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person<playProtocol> *p = [Person new];
[p playPCgame];//->Playing PC game now
Student *stu = [Student new];
[stu playPCgame];//->Playing PC game now
//Person<studyProtocol> *p2 = [Person new];编译器警告,因为Person类没有遵守studyProtocol协议
Student<studyProtocol> *stu2 = [Student new];
[stu2 studyOC];//->Studying OC now
}
return 0;
}