zoukankan      html  css  js  c++  java
  • 类别(分类)

    类别(分类)
    1. 为什么要使用分类
    问题:需要为已经存在的类添加新的功能,但是又不想为此创建子类。
    1)比如,如果需要为NSString添加一个功能,创建NSString类的子类将非常麻烦(因为NSString使用了底层的“类簇”)
    2)比如,需要为某个图像类UIImage添加一个网络加载图片的功能,但是仅为了该功能就创建一个子类,就不是很方便。因为任何想要使用该功能的图像对象,必须定义成这个子类类型,而不能定义成通用的UIImage类型,在使用上不方便。

    解决方案:使用分类

    1. 分类的使用
      分类的作用
      分类,用来给已有的类添加新的方法。
      分类,可以为任何已有的类添加方法,甚至可以为没有源代码的类添加方法。

    分类的局限性
    1)在分类中,不能添加实例变量
    2)在分类中,可以添加属性,
    但是不能在分类的implementation中使用@synthesize stringCount进行“属性合成”。
    注意,在分类中定义的属性,
    不会自动生成实例变量、getter以及setter方法
    3)如果分类中定义的方法和原有类的方法同名,则使用分类中的方法。
    即,分类中的名法的优先级更高。

    分类的格式
    和普通类的定义相似,
    接口部分:
    @interface 类名(分类名)
    ……
    @end
    实现部分:
    @implementation 类名(分类名)
    ……
    @end

    分类的文件名的命名规则
    分类的文件名可以任意定义,
    但是通常命名为 “类名+类别.h”, “类名+类别.m”

    分类的使用:
    包含分类的头文件后,使用对应的普通类即可。

    Demo
    给汽车类创建一个分类, 实现充电功能
    Car+Charge.h

    import “Car.h”

    @interface Car (Charge)
    - (void)carCharge;
    @end

    Car+Charge.m

    import “Car+Charge.h”

    @implementation Car (Charge)

    • (void)carCharge
      {
      NSLog(@”充电…”);
      }

    @end

    main.m

    import “Car.h”

    import “Car+Charge.h” //包含分类的头文件

    int main(int argc, const char * argv[]) {
    @autoreleasepool {
    Car *car = [Car new];
    [car carCharge]; //直接使用分类中的方法carCharge
    }
    return 0;
    }

    3.1 拆分类的实现文件(implementation部分)
    问题:
    类的实现部分,必须在同一个文件中。
    如果某个类的功能很多,实现文件将非常庞大,不便于该类的维护。

    解决方案:
    用分类把类的实现“分散”到多个文件中。
    可以把这个类按照不同功能,拆分到多个分类中实现。
    各个分类的@interface部分(接口部分)都放到该类的.h文件中。
    各个分类的@implementation部分(实现部分)则放到各自的.m文件中。

    Demo
    CategoryThing类
    //CategoryThing.h
    //类CategoryThing的接口
    @interface CategoryThing : NSObject
    {
    NSInteger thing1;
    NSInteger thing2;
    NSInteger thing3;
    }
    @end // CategoryThing

    //分类Thing1的接口
    @interface CategoryThing (Thing1)
    - (void)setThing1:(NSInteger)thing1;
    - (NSInteger)thing1;
    @end // CategoryThing (Thing1)

    //分类Thing2的接口

    @interface CategoryThing(Thing2)
    - (void)setThing2:(NSInteger)thing2;
    - (NSInteger)thing2;
    @end // CategoryThing (Thing2)

    //分类Thing3的接口
    @interface CategoryThing (Thing3)
    - (void)setThing3:(NSInteger)thing3;
    - (NSInteger)thing3;
    @end // CategoryThing (Thing3)
    //CategoryThing.m

    import “CategoryThing.h”

    @implementation CategoryThing

    • (NSString *)description
      {
      NSString *desc = [NSString stringWithFormat: @”%d %d %d”,
      thing1, thing2, thing3];
      return (desc);
      }

    @end

    分类Thing1的实现
    Thing1.m

    import “CategoryThing.h”

    @implementation CategoryThing (Thing1)
    - (void)setThing1:(NSInteger)t1
    {
    thing1 = t1;
    }

    • (NSInteger) thing1
      {
      return (thing1);
      }

    @end
    分类Thing2的实现
    Thing2.m

    import “CategoryThing.h”

    @implementation CategoryThing (Thing2)

    • (void)setThing2:(NSInteger) t2
      {
      thing2 = t2;
      }

    • (NSInteger)thing2
      {
      return (thing2);
      }

    @end // CategoryThing

    分类Thing3的实现
    Thing3.m

    import “CategoryThing.h”

    @implementation CategoryThing (Thing2)

    • (void)setThing3:(NSInteger) t3
      {
      thing3 = t3;
      }

    • (NSInteger)thing3
      {
      return (thing3);
      }

    @end
    3.2 用分类声明已有类的私有方法
    注意:该方式仅限于在开发阶段用于调试某些功能。
    代码中使用该方式,将不能通过苹果公司的审核,无法上架。

    类的私有方法
    类的@interface中声明的方法,是用来给他人使用的。
    但是在类的内部实现时,常常需要定义很多仅限于内部使用的方法。
    仅只能在类的方法中调用,不同通过对象调用。
    在@implementation部分中定义的方法都是私有方法。

    调用类的私有方法
    直接通过对象调用私有方法,将不能通过编译。
    解决方案:
    1)通过选择器@select调用。
    Demo
    假设Car类中有私有方法test
    Car *car = [Car new];
    //[car test]; error, 无法通过编译, 在car的Interface中没有找到test方法
    [car performSelector:@selector(test) withObject:nil]; //绕过编译检查,直接调用”私有”方法

    2)在分类中声明私有方法
    代码中使用该方式,将不能通过苹果公司的审核,无法上架。
    仅限于开发、调试阶段使用。

    4.类扩展
    类扩展,即“匿名分类”。

    类扩展和分类的比较
    1)类扩展在形式上和分类相似,只是没有分类的名称
    @interface 类名()
    ……
    @end

    1. 分类中不能定义实例变量
      类扩展中可以定义实例变量

    2. 文件的组织方式不同
      分类的实现部分@implementation一般都放在自己独立的.m文件中。
      类扩展的实现部分则必须放到已有类的@implementation中。

      类扩展的@interface部分可以放在独立的 .h文件中,
      一般都放在已有类的.m文件中。

    3. 分类中定义的属性、方法都是public的
      类扩展中定义的属性、方法、都是private的
      注:类扩展中,很少定义方法。
      因为可以直接在原有类的@implementation中定义私有方法。

    4. 使用目的不同
      分类用于给已有类添加public功能。
      类扩展是为了在类的内部添加实例变量、属性、方法。

  • 相关阅读:
    安装vue-cli时-4058报错的解决方法
    Sublime text 3 配置
    Vue项目本地run与build后样式不同,build后样式不生效
    npm run build 打包后,如何运行在本地查看效果(Nginx服务)
    JavaScript(ES6)学习笔记-Set和Map与数组和对象的比较(二)
    JavaScript(ES6)学习笔记-Set和Map数据结构(一)
    Angular
    本地项目与码云上的项目相关联
    获取GitHub上远程分支内容
    MyEclipse
  • 原文地址:https://www.cnblogs.com/Sico2Sico/p/5384280.html
Copyright © 2011-2022 走看看