黑马程序员-IOS基础之OC分类(Category)

来源:互联网 发布:淘宝商业摄影需要器材 编辑:程序博客网 时间:2024/06/04 14:24

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

Objective C之Category

分类的语法非常好用,在我们以后的开发中也会经常使用,那么分类怎么用呢?分类的英文是Category,因为这个单词是从国外翻译过来的,所有有人叫它分类,也有人叫它类别,一般我们叫它分类。那么它使用在什么场景呢?

我们新建一个Person类,并为这个类增加一个test方法(“-”,减号就代表对象方法嘛)。

Person.h类的声明代码如下:

#import <Foundation/Foundation.h>@interface Person : NSObject{int _age;}@property int age;- (void)test;@end

Person.m类的实现代码如下:

#import "Person.h"@implementation Person- (void)test{    NSLog(@"调用了test方法");}@end

那么,我要求给Person这个类再新增一个方法,但前提是不准改变Person类原来的代码。应用我们之前学过的知识可以使用继承,给Person扩充方法,如果不使用继承的话,那么我们又该怎么办呢?这个时候我们就要用到分类了。分类就是用来干这个事的,分类可以在不修改原来类的代码的前提下,给某个类扩充一些方法。我们给类扩充方法,试想一下,这个分类的格式是否和类的格式一样呢?

分类的格式,如下:

① //声明@interface 类名 (类名名称)  //分类名称一般为项目的模块名    ...@end② //实现@implementation 类名 (类名名称)    ...@end

实际操作流程:项目右击→NEW FILE→OS X下面的Cocoa→Objective C Category,然后Category分类名写:XP(XP是我名字的缩写,告诉别人这个类是我写的),Category on(你要给哪个类添加分类),我们这里写Person,创建完之后,就如下面,会有两个文件,默认是类名+分类名,这样我们就很容易分清,这个分类是给哪个类扩充的。

Person+XP.h类的声明代码如下:

#import <Person.h> //如果去掉,就找不到Person类@interface Person (XP)//为Person类增加一个study方法- (void)study;@end


Person+XP.m类的实现代码如下:

#import "Person+XP.h"@implementation Person (XP)- (void)study{    NSLog(@"这是给Person增加的study方法");}@end

那么我们就来调用一下

现在能感受到分类的好处了吗?好处就是,在以后的开发中,一个很庞大的类,庞大到一个类中有几百上千个方法,每个方法的功能都不一样,这个我们就可以把不同功能的方法,写到不同的类中。一个分类写一个功能,比如一个功能有几十个方法,我们就可以写到一个分类中,另外功能的方法,可以写到另外的分类中。每个功能都有一个名称,这样有利用团队开发。

#import <Foundation/Foundation.h>#import "Person.h" <span style="white-space:pre"></span>//自己写的类,我们导入的话,要用双引号,系统自带的,要用“<>”#import "Person+XP.h"#import "Person+XX.h"int main(){    Person *p = [[Person alloc] init];    [p test];//即可调用Person类中的test方法    //[p study];  如果我们调用study方法,是没有提示的,因为我们Person类中是没有study方法的    //study方法在Person+XP.h中,所以我们的引入 #import "Person+XP.h",然后再调用的话,就会有提示    //[p study];    return 0;}

我们现在再创建一个分类

Person+XX.h类的声明代码如下:

#import "Person.h"@interface Person (XX)- (void)test2;@end

Person+XX.m类的实现代码如下:

#import "Person+XX.h"@implementation Person (XX)- (void)test2{    NSLog(@"Person+XX的test2方法");}@end

那么,我们这时候Person类就有了三个方法test、study、test2。这三个方法是在三个不同的文件里面。这个时候我们如果要调用test2方法,我们就需要在main方法中导入头文件 #import "Person+XX.h",然后使用[p test2];就可以了。


下面我们就介绍分类的使用注意,也算是总结吧!

1.分类只能增加方法,不能增加成员变量,我们可以通过继承创建子类,为父类添加变量

把我们刚才写的代码拿出来,看一下

#import "Person+XP.h"@implementation Person (XP){    int _age;//这句话是会立马报错的!}- (void)study{    NSLog(@"这是给Person增加的study方法");}@end

2.分类方法实现中可以访问原来类中声明的成员变量

#import "Person+XP.h"@implementation Person (XP)- (void)study{    NSLog(@"这是给Person增加的study方法");    NSLog(@"age = %d",_age);//分类中是可以访问原来类中声明的变量}@end

如果在main方法中,给p对象的属性age赋值为10;p.age = 10;那么Person+XP.m中就会打印出 age = 10; 

3.分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,导致原来的方法没法使用。

#import "Person+XP.h"@implementation Person (XP)- (void)study{    NSLog(@"这是给Person增加的study方法");    NSLog(@"age = %d",_age);//分类中是可以访问原来类中声明的变量}- (void)test<span style="white-space:pre">//Person类中也有一个叫test的方法{    NSLog(@"Person+XP的test方法");//这个会覆盖掉Person类中的test方法,导致Person类中的test方法没法使用}@end

4.多个Category中实现了相同的方法,只有最后一个参与编译才会有效

#import "Person+XX.h"@implementation Person (XX)- (void)test{    NSLog(@"Person+XX的test方法");//这个会覆盖掉Person类中的test方法,导致Person类中的test方法没法使用}@end

我们知道会覆盖掉父类中的方法,但是在Person+XP.m和Person+XX.m中都有test方法,到底会执行那个分类中的test方法呢?哪个分类最后编译,就执行那个分类的里面的test方法


优先级:优先去分类中查找,然后去原来类中找,最后再去父类中找。

分类(最后参与编译的分类优先)→原来类→父类


分类的应用


给NSString增加类方法:

之前我们都是在给Person类增加分类,Person类是我们自己定义的类,但是实际上,在以后的开发过程中,很多情况下,比一定是给自己的类增加分类,而是给系统自带的类增加分类,那为什么呢?我们学过两个系统自带的类,一个是NSObject,另一个就是NSString,系统类都提供了很多好用方法给我们,但是在实际的开发过程中,不能满足我们的需求,这个时候我们就要为系统自带的类扩充方法。


分类的好处:

1.一个庞大的类可以分模块开发;

2.一个庞大的类可以由多个人来编写,更有利于团队合作;


需求:

给NSString增加一个类方法,计算某个字符串中的阿拉伯数字的个数;

给NSString增加一个对象方法,计算当前字符串中阿拉伯数字的个数;

创建一个项目,增加一个类文件NSString+Number

NSString+Number.h类的声明代码如下:

#import <Foundation/Foundation.h>@interface NSString (Number)+ (int)numberCountOfString:(NSString *)str;//NSString类方法- (int)numberCount;//NSString对象方法@end

NSString+Number.m类的实现代码如下:

#import "NSString+Number.h"@implementation NSString (Number)+ (int)numberCountOfString:(NSString *)str{    //定义变量计算数字的个数(局部变量一定要初始化)    int count = 0;    for(int i = 0; i < str.length; i++)    {unichar c = [str characterAtIndex:i];if( c >= '0' && c <= '9'){count++;}    }    return count;}- (int)numberCount{    int count = 0;    for(int i = 0; i < self.length; i++)   {        //取出i这个位置对应的字符        unichar c = [self charcterAtIndex:i];//如果c是阿拉伯数字,count就自增一次        if( c >= '0' && c <= '9')        {            count++;        }    }    return count;}@end

main方法里面调用

#import <Foundation/Foundation.h>int main(){    //int count = [NSString numberCountOfString:@"54354dsd"];    //NSLog(@"%d",count); //打印出来的结果为 5    return 0;}

如果要算出@"542454dsd"这个对象,就直接设计成如下

[@"542454dsd" numberCount];//这样写,就可以体现面向对象的思想




0 0