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功能。
      类扩展是为了在类的内部添加实例变量、属性、方法。

  • 相关阅读:
    June 26th 2017 Week 26th Monday
    June 25th 2017 Week 26th Sunday
    June 24th 2017 Week 25th Saturday
    June 23rd 2017 Week 25th Friday
    June 22nd 2017 Week 25th Thursday
    2018最佳网页设计:就是要你灵感爆棚!!!
    图片素材类Web原型制作分享-Pexels
    想要打动HR的心,UX设计师求职信究竟应该怎么写?
    【UXPA大赛企业专访】Mockplus:“设计替代开发”将成为现实
    2018年最好的医疗网站设计及配色赏析
  • 原文地址:https://www.cnblogs.com/Sico2Sico/p/5384280.html
Copyright © 2011-2022 走看看