A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© lixiaopeng 中级黑马   /  2015-7-23 21:35  /  638 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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

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

Person.h类的声明代码如下:
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface Person : NSObject  
  4. {  
  5. int _age;  
  6. }  
  7. @property int age;  
  8.   
  9. - (void)test;  
  10.   
  11. @end  
复制代码

Person.m类的实现代码如下:
  1. #import "Person.h"  
  2.   
  3. @implementation Person  
  4.   
  5. - (void)test  
  6. {  
  7.     NSLog(@"调用了test方法");  
  8. }  
  9.   
  10. @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类的声明代码如下:
  1. #import <Person.h> //如果去掉,就找不到Person类  
  2.   
  3. @interface Person (XP)  
  4. //为Person类增加一个study方法  
  5. - (void)study;  
  6. @end  
复制代码

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

  1. #import "Person+XP.h"  
  2.   
  3. @implementation Person (XP)  
  4. - (void)study  
  5. {  
  6.     NSLog(@"这是给Person增加的study方法");  
  7. }  
  8. @end  
复制代码


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

  1. #import <Foundation/Foundation.h>  
  2. #import "Person.h"  </span>//自己写的类,我们导入的话,要用双引号,系统自带的,要用“<>”  
  3. #import "Person+XP.h"  
  4. #import "Person+XX.h"  
  5. int main()  
  6. {  
  7.     Person *p = [[Person alloc] init];  
  8.     [p test];//即可调用Person类中的test方法  
  9.     //[p study];  如果我们调用study方法,是没有提示的,因为我们Person类中是没有study方法的  
  10.     //study方法在Person+XP.h中,所以我们的引入 #import "Person+XP.h",然后再调用的话,就会有提示  
  11.     //[p study];  
  12.     return 0;  
  13. }  
复制代码


我们现在再创建一个分类

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


  1. #import "Person.h"  
  2.   
  3. @interface Person (XX)  
  4.   
  5. - (void)test2;  
  6.   
  7. @end  
复制代码


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

  1. #import "Person+XX.h"  
  2.   
  3. @implementation Person (XX)  
  4.   
  5. - (void)test2  
  6. {  
  7.     NSLog(@"Person+XX的test2方法");  
  8. }  
  9.   
  10. @end  
复制代码


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


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

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

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

  1. #import "Person+XP.h"  
  2.   
  3. @implementation Person (XP)  
  4. {  
  5.     int _age;//这句话是会立马报错的!  
  6. }  
  7. - (void)study  
  8. {  
  9.     NSLog(@"这是给Person增加的study方法");  
  10. }  
  11. @end  
复制代码


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

  1. #import "Person+XP.h"  
  2.   
  3. @implementation Person (XP)  
  4. - (void)study  
  5. {  
  6.     NSLog(@"这是给Person增加的study方法");  
  7.     NSLog(@"age = %d",_age);//分类中是可以访问原来类中声明的变量  
  8. }  
  9. @end  
复制代码


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

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

  1. #import "Person+XP.h"  
  2.   
  3. @implementation Person (XP)  
  4. - (void)study  
  5. {  
  6.     NSLog(@"这是给Person增加的study方法");  
  7.     NSLog(@"age = %d",_age);//分类中是可以访问原来类中声明的变量  
  8. }  
  9. - (void)test                         //Person类中也有一个叫test的方法  
  10. {  
  11.     NSLog(@"Person+XP的test方法");//这个会覆盖掉Person类中的test方法,导致Person类中的test方法没法使用  
  12. }  
  13. @end  
复制代码


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

  1. #import "Person+XX.h"  
  2.   
  3. @implementation Person (XX)  
  4.   
  5. - (void)test  
  6. {  
  7.     NSLog(@"Person+XX的test方法");//这个会覆盖掉Person类中的test方法,导致Person类中的test方法没法使用  
  8. }  
  9. @end  
复制代码


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


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

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



分类的应用



给NSString增加类方法:

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



分类的好处:

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

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



需求:

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

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

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

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

  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface NSString (Number)  
  4.   
  5. + (int)numberCountOfString:(NSString *)str;//NSString类方法  
  6. - (int)numberCount;//NSString对象方法  
  7.   
  8. @end  
复制代码


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

  1. #import "NSString+Number.h"  
  2.   
  3. @implementation NSString (Number)  
  4.   
  5. + (int)numberCountOfString:(NSString *)str  
  6. {  
  7.     //定义变量计算数字的个数(局部变量一定要初始化)  
  8.     int count = 0;  
  9.     for(int i = 0; i < str.length; i++)  
  10.     {  
  11.     unichar c = [str characterAtIndex:i];  
  12.     if( c >= '0' && c <= '9')  
  13.     {  
  14.         count++;  
  15.     }  
  16.     }  
  17.     return count;  
  18. }  
  19.   
  20. - (int)numberCount  
  21. {  
  22.     int count = 0;  
  23.     for(int i = 0; i < self.length; i++)  
  24.    {  
  25.         //取出i这个位置对应的字符  
  26.         unichar c = [self charcterAtIndex:i];  
  27.     //如果c是阿拉伯数字,count就自增一次  
  28.         if( c >= '0' && c <= '9')  
  29.         {  
  30.             count++;  
  31.         }  
  32.     }  
  33.     return count;  
  34. }  
  35. @end  
复制代码


main方法里面调用

  1. #import <Foundation/Foundation.h>  
  2.   
  3. int main()  
  4. {  
  5.     //int count = [NSString numberCountOfString:@"54354dsd"];  
  6.     //NSLog(@"%d",count); //打印出来的结果为 5  
  7.     return 0;  
  8. }  
复制代码


如果要算出@"542454dsd"这个对象,就直接设计成如下
[@"542454dsd" numberCount];//这样写,就可以体现面向对象的思想

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马