黑马程序员——OC的Category和Protocol

来源:互联网 发布:宁波奥凯网络 编辑:程序博客网 时间:2024/06/05 11:12

———-android培训、Java培训、iOS培训,期待与您交流———-

Category

一、基本概念

  1. 分类的作用:

    • 在不修改原有的类的基础上增加新的方法
    • 一个庞大的类可以分模块开发,便于维护
    • 一个庞大的类可以由多个人来编写,更有利于团队合作
  2. 使用类别的目的

    • 对现有类进行扩展:对自定义的类甚至是框架中的类进行扩展,从而实现项目特殊需求。
    • 作为子类的替代手段:不需要定义和使用一个子类,可以通过类别直接向已有的类中增加方法。
    • 对类中的方法归类:利用category把一个庞大的类划分为小块来分别进行开发,从而更好的对类中的方法进行更新和维护。
  3. 关于非正式协议

    为NSObject添加的分类就称作非正式协议。非正式协议一般不需要进行实现,而是在子类中进行方法的重写。

二、分类的使用

1.分类的实现步骤

  1. 声明

    格式:

    @interface 待扩展的类名 (分类的名称)

    @end

  2. 实现

    格式:

    @implementation 待扩展的类名 (分类的名称)

    @end

  3. 文件的命名格式:

    待扩展的类名+分类名称

  4. 使用

    与使用类中原有的方法一样,用方括号调用。

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.协议的使用流程

  1. 定义协议(在.h文件中)

    在当前target中新建Objective-C文件,File Type选择Protocol。

    格式:

    @protocol 协议名称 <NSObject>  //默认遵守NSObject协议//方法声明列表 @end;
  2. 采用(遵守)协议

    • 类遵守协议

      创建类的时候遵守某个或者某几个协议

    @interface 类名 : 父类 <协议名称1,协议名称2>@end
    • 协议遵守协议

      协议也可以遵守一个或多个其他协议

    @protocol 协议名称 <其他协议名称1,其他协议名称2>@end
  3. 实现协议要求实现的方法

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;}
0 0