category

一 category的概念
分类的目的是在不改变原先类的基础上以达到扩展类方法的目的。category是OC特有的语法,在C中并没有分类的概念。
二 category的作用
1)不修改原类,而为原类增加方法
2)修改原类中某些方法的bug,即让分类方法覆盖原类旧方法
3)将类的内容存储在多个文件中
4)便于团队开发合作
5) 将常用的相关的方法分组
三 cagegory的用法格式
头文件格式:
@interface 类名 (分类名称)
@end
实现文件格式:
@implementation 类名 (分类名称)
@end
使用过程中要加入原类的头文件,否则不会识别类名
四 category的测试用例
例1:分类和原类完全分开

//main.m
#import <Foundation/Foundation.h>
#import "animal+animal_ext.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {     
        animal *a1 = [animal new];
        [a1 run];  //原类方法
        [a1 legs:4]; //分类方法
        [a1 printleg]; //原类方法
    }
    return 0;
}
//原类.h和.m文件
//  animal.h

#import <Foundation/Foundation.h>
#import "animal.h"
@interface animal : NSObject
@property (nonatomic,assign) int leg;
-(void) run;
-(void) printleg;
@end
/***************************************/
//  animal.m

#import "animal.h"
@implementation animal
-(void) run
{
    NSLog(@"the animal is running");
}
-(void) printleg
{
    NSLog(@"the animal has %d legs",_leg);
}
@end
//分类.h和.m文件
//  class1+animal_ext.h

#import "animal.h"
@interface animal (animal_ext)
-(void) legs:(int)d;
@end
/***************************************/
//  class1+animal_ext.m

#import "animal+animal_ext.h"

@implementation  animal (animal_ext)
-(void) legs:(int)d
{
    self.leg = d; //分类访问原类变量
}
@end

程序运行结果:
这里写图片描述

可见分类可以访问原类的变量,访问方式是用self访问。

下面增加animal有子类(dog类),让它重写原类printleg方法,以及查看是否能使用分类方法

//dog类.h和.m文件
//  dog.h

#import "animal.h"

@interface dog : animal
@end
/***************************************/
//  dog.m
#import "dog.h"

@implementation dog
-(void) printleg
{
    NSLog(@"dog has %d legs",self.leg);
}
@end

运行结果:

这里写图片描述

由上图可以看到,dog类重写了原类的printleg方法以适应dog自己的特点,而且它也继承了原类的分类方法。
如果有原类有多个分类,而且有方法名重复,那么子类在调用会调用最后一次编译的那个分类中的方法。如图:
这里写图片描述

例2:category的非正式协议

//  main.m

#import <Foundation/Foundation.h>
#import "person.h"
#import "NSObject+category.h"

int main(int argc, const char * argv[])
{
    @autoreleasepool {
                person *per = [person new];
        [per print];
    }
    return 0;
}
//给NSObject增加的分类
//  NSObject+category.h

#import <Foundation/Foundation.h>

@interface NSObject (NSObject_category)
-(void) print;
@end
/***************************************/
//  NSObject+category.m

#import "NSObject+category.h"

@implementation NSObject (NSObject_category)

-(void) print
{
    NSLog(@"我是非正式协议");
}
@end
//继承NSObject
//  person.h

#import <Foundation/Foundation.h>
@interface person : NSObject

@end
/***************************************/
//  person.m

#import "person.h"

@implementation person

@end

运行结果:
这里写图片描述

可见为NSObject增加分类的话,那么继承它的类都可以使用分类,所以 这个部分要好好考虑要不要增加分类,如果增加也要增加一个通用的分类。否则会造成意想不到的后果。
例3:category的Extention
它是cagegory的一个特例,没有分类名字,它可以分原类添加变量
下面是例子的代码,代码的其它部分和例1一样,就不再写了,这里只写extention代码和man.m中,以及原类的实现的代码

//修改过的main.m,主要是分了测试extention
//  main.m

#import <Foundation/Foundation.h>
#import "animal+animal_ext.h"
#import "animal_extention.h"
#import "dog.h"
int main(int argc, const char * argv[])
{
    @autoreleasepool {       
        animal *a1 = [animal new];
        [a1 run];  //原类方法
        [a1 legs:4]; //分类方法
        [a1 printleg]; //原类方法

        dog *d1 = [dog new];
        [d1 legs:4];
        [d1 printleg];

        [d1 eat:6];
    }
    return 0;
}
//新增加的extention头文件
//  animal_extention.h

#import "animal.h"

@interface animal ()
{
    int maxfood; //扩展变量
}
-(void) eat:(int) food;//扩展方法
@end
//animal.h没有改变只改变了animal.m
//  animal.m

#import "animal.h"
#import "animal_extention.h"

@implementation animal
-(void) run
{
    NSLog(@"the animal is running");
}
-(void) printleg
{
    NSLog(@"the animal has %d legs",_leg);
}
-(void) eat:(int) food //扩展方法
{
    maxfood = food;
    NSLog(@"动物的食量是%d",maxfood);
}
@end

运行结果:
这里写图片描述
由例3可知,扩展的变量是相对私有变量,不能被继承,只能被当前类实用。
如果将扩展的声明和实现全部定在原类的.m中那么扩展的方法也是私有的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俯仰一世_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值