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

------<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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值