• 分类和扩展


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

    首先是分类(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、上面总结的第四条中,分类中是不能添加实例变量,但是可以添加属性。

  • 相关阅读:
    redis基础
    docker日志清理脚本
    Hive修改表的所有者(Owner)
    User xxx does not have privileges for CREATETABLE的解决办法
    Spark读取Hive表中文显示乱码的解决办法
    Go语言之标识符与关键字
    Go语言之数据类型(三)
    bootstrapTable频繁向后台接口发请求
    框架整合疑云
    业务开发中-设计模式使用
  • 原文地址:https://www.cnblogs.com/zhanggui/p/4740274.html
Copyright © 2020-2023  润新知