一、Categories(分类)
     Categories是一个把单个类定义分作好几个文件的方式。它的目标是通过模块化减少代码量比较大的压力。这避免了你的代码成为1000+行的文件,这样操作和分配精确几乎是不可能的。一个好的类定义是一个独特开发者必须的。
          
     这个图是用多个文件来实现Car类。
 
           在这个模块,我们在不接触它的类原始文件的情况下,使用分类来扩展已经存在的类。我们将学到如何使用这个功能来仿生保护方法(Protected methods)。Extensions和category关联很大,一会再说。
     设置
           再我们开始试验categories时,我们需要一个类去操作,创建/改变你的已经存在的类,代码如下:
       Car.h
#import <Foundation/Foundation.h>

@interface Car : NSObject

@property(copy,nonatomic)NSString *model;
@property(readonly) double odometer; -(void)startEngine;
-(void)drive;
-(void)turnLeft;
-(void)turnRight;
@end
它的实现知识一些描述消息,因此我么可以再不同方法调用时发现。
#import "Car.h"
@implementation Car

-(void)startEngine
{
NSLog(@"starting the %@'s engine" ,_model);
}
-(void)drive
{
NSLog(@"The %@ is now driving",_model);
}
-(void)turnLeft
{
NSLog(@"The %@ is turning left",_model);
}
-(void)turnRight
{
NSLog(@"The %@ is turn right",_model);
}
@end
现在,让我们添其他方法到Car中,我们不去操作Car.h或者Car.m文件,我们可以用一个专用的分类去放置自己的函数方法。
创建Categories
     File—>New File—>iOS中选择Source—>Objective-C File,然后就会看到下图的选项,File Type 包括Empty File,Category,Protocol和Extension。
          File是文件名,Class是你想要扩展的类。
          当我们创建完成后,会生成两个文件,一个Car+Maintenance.h和一个Car+Maintenance.m
           Car+Maintenance.m
#import "Car+Maintenance.h"

@implementation Car (Maintenance)

@end  
       分类名字的约束是一个类的不同分类名字不能相同。正宗的文件命名协定是用类名+分类名。
        在Car+Maintenance.h
#import "Car.h"

@interface Car (Maintenance)

@end
     我们可以看到,它几乎和其他的类一样,只不过多了一个小括号,里面是分类名称,让我们添加一些新的方法到这里:
#import "Car.h"

@interface Car (Maintenance)

-(BOOL)needsOilChange;
-(void)changeOil;
-(void)rotateTires;
-(void)jumpBatteryUsingCar:(Car *)anotherCar;
@end
     在运行的时候,他们就会成为类的一部分,尽管他们没有在一个文件中声明,你可以像访问原始文件中的方法一样去访问分类中的方法。
     当然了,你必须去实现这些方法。它的实现和原始文件实现几乎一样,除了类名称后面多了一个括号。
#import "Car+Maintenance.h"

@implementation Car (Maintenance)

-(BOOL)needsOilChange {
return YES;
}
-(void)changeOil {
NSLog(@"Changin oil for the %@",[self model]);
}
-(void)rotateTires {
NSLog(@"Rotation tires for the %@",[self model]);
}
-(void)jumpBatteryUsingCar:(Car *)anotherCar {
NSLog(@"Jumped the %@ with a %@",[self model],[anotherCar model]);
}
@end
    还有重要的一点,分类也可以用于重写在原始类文件中已经存在的方法,(例如startEngine method),但是千万不要这样做。原因是分类是扁平式组织结构,如果你重写已经存在的方法,OC就不知道该调用哪个方法,在这种情况下,子类化是一个更好的选择。
  使用Categories
    要想使用分类只需要把.h文件导入即可,这样分类中的方法即可使用。
  #import "Car+Maintenance.h"
如果你删除了分类,那么你就会找不到定义的方法。
  保护方法(Protected)
     但是,分类并不是简单的把类定义放到几个文件中,他是一个强大的组织工具。我们可以定义类似保护访问的修改器,方法是在一个专用的分类中,定义一个protected 接口,然后之把它导入父类实现文件中,这样就定义了保护方法,而且使它们保持隐蔽。例如我们创建Car+Protected.h,然后直接导入父类的实现文件中。
#import "Car.h"
#import "Car+Protected.h" @implementation Car
...
- (void)drive {
[self prepareToDrive];
NSLog(@"The %@ is now driving", _model);
}
...

就像上边这样。

二、Extensions(扩展)
     它和分类很像,都是在原始类文件之外,允许你添加新的方法。但是与分类形成对照。extension’API必须再主实现中实现,它不能在分类中实现。
     记住一点,私有方法可以用把分类引入到实现文件中(而不是接口文件)实现私有效果,这些再你有很少的私有方法时可以实现,但是对于一个比较大的类就显得比较笨拙,扩展就是解决这个问题,它允许你声明正式的私有API.
     例如,如果你想把engineIsWorking方法正式的加入到Car中,你可以在Car.m包括一个扩展.它仍是一个私有方法,扩展的语法就像一个空的分类。
#import "Car.h"
@interface Car ()
-(BOOL)engineIsWorking;
@end
     它只有一个.h文件。然后在Car.m中去实现:
#import "Car.h"
#import "Car_Car.h"
@implementation Car -(void)startEngine
{
NSLog(@"starting the %@'s engine" ,_model);
}
-(void)drive
{
NSLog(@"The %@ is now driving",_model);
}
-(void)turnLeft
{
NSLog(@"The %@ is turning left",_model);
}
-(void)turnRight
{
NSLog(@"The %@ is turn right",_model);
}
-(BOOL)engineIsWorking {
return YES;
}
@end
     另外,为了声明一个正式的私有API,扩展还可以重定义属性。这通常是用来使属性就像读写属性一样,同时保持只读到其他对象中。
     例如:
#import "Car.h"

@interface Car ()
@property(readwrite) double odometer;
-(BOOL)engineIsWorking;
@end
     我们可以在内部实现中指定self.odometer的值,但是再Car.m外就会编译失败。
三、总结
     分类是把类模块化道不同文件中的一种方式。扩展提供相似的功能,除了他的API必须要在主实现中公开。
      在组织大量代码库时,最常见的分类使用就是给内置数据类型(NSString 、NSArray)添加方法。这样的优点在于,你不需要去创建一个子类更新存在的代码,但是必须要小心不要去重写已经存在的方法。对于小的工程,分类完全没有必要使用,可以用协议或者子类化去实现这种功能。
     
     

Categories  VS Extensions (分类 vs 扩展)的更多相关文章

  1. iOS开发---分类和扩展(Categories和Extensions)

      1.分类能够做到的事情主要是:即使在你不知道一个类的源码情况下,向这个类添加扩展的方法.   此外,分类能够保证你的实现类和其他的文件区分开.   1 #import “UIViewControl ...

  2. (转)iOS分类和扩展(Categories和Extensions)

    分类(Category)   分类能够做到的事情主要是:即使在你不知道一个类的源码情况下,向这个类添加扩展的方法.   此外,分类能够保证你的实现类和其他的文件区分开. #import “UIView ...

  3. iOS 类别和扩展(Categories和Extensions)

    分类(Category)   分类能够做到的事情主要是:即使在你不知道一个类的源码情况下,向这个类添加扩展的方法.   此外,分类能够保证你的实现类和其他的文件区分开.   1 #import “UI ...

  4. iphone 开发Categories 、Extensions 区别 --转

    Category和Extension这两个概念,即便对于Java程序员,可能也会感到陌生.这是Objective C为程序员提供的两个强大的动态机制——简单地说,它们允许程序员为已有的对象添加新的方法 ...

  5. 8.2.1.7 Use of Index Extensions 使用索引扩展

    8.2.1.7 Use of Index Extensions 使用索引扩展 InnoDB 自动扩展每个secondary index 通过添加primary key columns to it,考虑 ...

  6. iOS项目开发日常之创建文件(协议、类、分类、扩展)

    iOS项目开发过程中,是以不断创建文件的形式进行着的. 创建得比较频繁的文件类型是: 这两个类型中创建的文件有:子类.分类.扩展.协议四种文件,如下:    这四类文件是频繁创建的,我们来看一下各自分 ...

  7. iOS中的分类和扩展

    一.什么是分类? 概念:分类(Category)是OC中的特有语法,它是表示一个指向分类的结构体指针.根据下面源码组成可以看到它没有属性列表,原则上是不能添加成员变量(其实可以借助运行时功能,进行关联 ...

  8. Swift基础--Swift中的分类以及在分类中扩展init方法的注意事项

    Swift中的分类 1.创建一个空的swift文件 2.关键字extension,格式: extension 要扩展的类名 {} extension UIButton { } Swift中扩展init ...

  9. Celery-4.1 用户指南: Extensions and Bootsteps (扩展和Bootsteps)

    自定义消息消费者 你可能想要嵌入自定义的 Kombu 消费者来手动处理你的消息. 为了达到这个目的,celery 提供了一个 ConsumerStep bootstep 类,你只需要定义 get_co ...

随机推荐

  1. Linux常用命令-vim

    vim的基本模式 1普通模式Normal mode 输入vim命令后进入的就是普通模式. 2插入模式Insert mode 这是内容修改编辑的模式, 在普通模式进入插入模式方法 按i或insert 在 ...

  2. linux centos7 root密码重置

    转:http://blog.chinaunix.net/uid-21209618-id-4738916.html 分类: LINUX 三年左右没接触linux技术工作,忘记的有很多.不知该怎么去运用. ...

  3. Python机器学习笔记:利用Keras进行分类预测

    Keras是一个用于深度学习的Python库,它包含高效的数值库Theano和TensorFlow. 本文的目的是学习如何从csv中加载数据并使其可供Keras使用,如何用神经网络建立多类分类的数据进 ...

  4. 【图文详细教程】maven3安装配置+eclipse离线安装maven3插件《《唯一成功的教程~~~2018-01-09》》

    环境搭建前提: 1.电脑上已经安装了1.7以及以上版本的JDK(因为我提供的maven版本是最新的3.3.9的,要求最低JDK1.7) 2.配置好了ecplise并且能正常启动 第一步:下载maven ...

  5. 乐字节-Java8新特性之Base64和重复注解与类型注解

    上一篇小乐给大家说了<乐字节-Java8新特性之Date API>,接下来小乐继续给大家说一说Java8新特性之Base64和重复注解与类型注解. 一.Base64 在Java 8中,内置 ...

  6. 前端面试(原生js篇) - 精确运算

    一.面试题 问:开发的时候有用到过 Math 吗? 答:很多啊.比如生成 GUID 的时候,就会用到 Math.random() 来生成随机数. 问:别的呢?比如向下取整.向上取整? 答:向下取整是  ...

  7. Layui treeGrid

    目前treeGrid的源码不是很完善, 没有开放, 只有社区里面有, 想用的可以看看下面方法: 1.加入treeGrid.js文件 (1)layui 的treeGrid 下载地址:    https: ...

  8. Git应用—03分支管理和冲突解决(转载)

    Git 分支管理和冲突解决 https://www.cnblogs.com/mengdd/p/3585038.html 创建分支 git branch 没有参数,显示本地版本库中所有的本地分支名称. ...

  9. MySQL写入用户微信名

    很简单的需求,将用户微信名写入MySQl即可,但是测试过程中却遇到了问题,微信名中的emoji写入数据库失败.解决步骤如下 1.了解utf8mb4 MySQL从5.5.3版本开始支持utf8mb4编码 ...

  10. puppeteer入门

    转自: https://www.jianshu.com/p/a89d8d6c007b 作者: ppCode puppeteer新手入门(chromium下载跳坑) ppCode 关注 2017.12. ...