分类和扩展

原来写过一个解释很详细的分类和扩展的博客,感觉不是太直观,但是讲的很详细,今天就以一个简单的小例子来讲解一下。

首先是分类(Category)

它的作用就是为一个已有的类添加新的方法。说白了就是对类的扩展。看一下下面的例子:

首先我们新建一个Person类,该类继承自NSObject:

Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@end

Person.m

#import "Person.h"

@implementation Person

@end

我们可以在该类中声明我们需要的属性和方法。然后使用该类。这些都没有问题。但是有个比较奇葩的想法。我想让NSObject有个eat的方法,然后我在Person中去直接使用,就相当于调用了父类的eat方法,而且这个方法还不能在Person中实现。所以就会想到通过分类实现。

我们可以新建一个分类:File-->new-->然后在iOS中选择Objective-C File,然后填写File名称,File Type:(Extension/Protocol/Category/Empty File)。我们选择Category,然后设置Class为NSObject(Person的父类)。这里File名称我定为Category。完成后我们就会看到项目中多了两个我们刚才新建的那两个文件:

NSObject+Category.h和NSobject+Category.m。这就是我们新建的分类文件。看一下他的内容:

NSObject+Category.h:

#import <Foundation/Foundation.h>

@interface NSObject (Category)

@end

NSobject+Category.m

#import "NSObject+Category.h"

@implementation NSObject (Category)

@end

然后我们可以对上面的类中添加方法eat,添加过后的代码:

NSObject+Category.h

#import <Foundation/Foundation.h>

@interface NSObject (Category)

- (void)eat;
@end

NSObject+Category.m

#import "NSObject+Category.h"

@implementation NSObject (Category)

- (void)eat {
    NSLog(@"调用分类中的文件,然后使劲吃");
}
@end

这样一个添加有eat方法的NSObject分类就建好了。该怎么使用呢?看下边:

我们直接在Person.h中导入NSObject+Category.h文件:

#import <Foundation/Foundation.h>
#import "NSObject+Category.h"
@interface Person : NSObject

@end

然后我们就可以在ViewController或者main类中开始使用了:(我是在ViewControlelr中直接使用的)

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [Person new];
    [person eat];
    // Do any additional setup after loading the view, typically from a nib.
}

@end

这样我们实例化的person就有了eat的方法了。

什么?项目中有什么用?

在项目中,举个栗子,在项目中我们可能会去处理时间,比如让时间以指定的格式去显示,这个时候可能项目中有好多地方都需要去使用这个时间处理。我们总不能一个一个都写吧,我们可以新建一个NSDate的分类,然后在里面写一个类方法。这样我们在需要的地方直接去导入该NSDate的分类,然后直接使用就行了。(当然你也可以直接在BaseViewController中或者Global中去定义,都可以)。

看的累么?如果累就继续往下看扩展吧。

什么是扩展勒?刚才你会发现我们用分类给已有的类添加了新的方法,那么你可以不可以在分类中添加新的属性呢?你可以试试。我试了,不行,不行,不行。那怎么办?那就靠扩展了。它可以给已有的类添加属性。那么厉害?对,就是那么厉害?

就那刚才的Person类,我们想定义一个idCard属性,要求不能在Person.h中定义,那么我们可以新建一个NSObject的扩展。怎么建呢?和刚才建分类一样,只不过把File Type改成Extension就行了。建完后会看到这个:

由于我输入的File name是Extenstion所以在项目文件夹里多了一个文件。一个文件?对的,没有错扩展只是生成了一个NSObject_Extension.h文件。.m不知道跑哪里了。添加idCard的扩展如下:

#import <Foundation/Foundation.h>

@class NSString;
@interface NSObject ()

@property (nonatomic,copy)NSString *idCard;
@end

怎么使用呢?和刚才一样,导入.h即可:

#import "ViewController.h"
#import "Person.h"
#import "NSObject_Extenstion.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [Person new];
    [person eat];
    person.idCard = @"1312323423534543";
    // Do any additional setup after loading the view, typically from a nib.
}

@end

这样我们的Person类就有一个属性idCard了。

说了这么多?你应该可以理解把?不理解?看看下边的总结:

----------------------------------------------这里是总结----------------------------------------------

1、分类(Category)是可以给现有的类去添加方法的。但是注意尽量不要去重写该类已有的方法。(我刚才试了一下,直接Crash了,还提示分类正在实现一个该类自身的私有类警告)。反正不管怎么着,尽量不要去重写该类的方法。

2、扩展(Extension)是可以给现有的类添加属性(实例变量)的。

3、你说可以在扩展中添加方法吗?你试试。我试了,不行,再说了,要知道在扩展里添加方法我们去哪里实现呢?.m都没有。。。。

4、你说可以在分类中添加属性吗?你也试试,我试了(添加name)。再分类的.m文件中说name需要name方法定义-使用@dynamic或者提供方法来实现在category中。我定义之后还是直接Crash。说明在分类中添加属性行不通。

----------------------------------------------结束语----------------------------------------------

就这么多吧,如果有什么错误欢迎指正。谢谢。

---------------------------------------------修改----------------------------------------------

1、上面总结的第四条中,分类中是不能添加实例变量,但是可以添加属性。

原文地址:https://www.cnblogs.com/zhanggui/p/4740274.html