一、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. 前端回顾:2016年 JavaScript 之星

    JavasScript社区在创新的道路上开足了马力,曾经流行过的也许一个月之后就过时了.2016已经结束了.你可能会想你是否错过一些重要的东西?不用担心,让我们来回顾2016年前端有哪些主流.通过比较 ...

  2. 【awesome-dotnet-core-learning】(2)-Sprache.Calc-表达式计算器

    [awesome-dotnet-core-learning](2)-Sprache.Calc-表达式计算器 示例代码托管在GITHUB上, 欢迎STAR! 严格来说, Sprache.Calc只是上一 ...

  3. JavaWeb学习 (十七)————JSP属性范围

    所谓的属性范围就是一个属性设置之后,可以经过多少个其他页面后仍然可以访问的保存范围. 一.JSP属性范围 JSP中提供了四种属性范围,四种属性范围分别指以下四种: 当前页:一个属性只能在一个页面中取得 ...

  4. [PHP] 算法-二位有序数组中查找的PHP实现

    在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 1.二 ...

  5. 表数据量影响MySQL索引选择

    现象 新建了一张员工表,插入了少量数据,索引中所有的字段均在where条件出现时,正确走到了idx_nap索引,但是where出现部分自左开始的索引时,却进行全表扫描,与MySQL官方所说的最左匹配原 ...

  6. 在UAP中如何通过WebView控件进行C#与JS的交互

    最近由于项目需求,需要利用C#在UWP中与JS进行交互,由于还没有什么实战经验,所有就现在网上百度了一下,但是百度的结果显示大部分都是在Android和IOS上面的方法,UWP中的几乎没有.还好微软又 ...

  7. C#特性:ConditionalAttribute

    ConditionalAttribute类 msdn解释: 指示编译器应忽略方法调用或属性,除非已定义指定的条件编译符号. 命名空间: System.Diagnostics 语法: // // 摘要: ...

  8. ECMAScript正则表达式6个最新特性

    译者按: 还没学好ES6?ECMAScript 2018已经到来啦! 原文:ECMAScript regular expressions are getting better! 作者: Mathias ...

  9. JS校验身份证号的合法性

    前端表单中有身份证号的校验,下边是用JS来校验身份证号的合法性. 中国居民身份证号码编码规则 第一.二位表示省(自治区.直辖市.特别行政区). 第三.四位表示市(地级市.自治州.盟及国家直辖市所属市辖 ...

  10. 【读书笔记】iOS-正则表达式

    正则表达式通常称为regexes,是文本处理中模式匹配的一个标准,也是处理字符串的一个强有力的工具.使用正则表达式时,需要指定一个字符串作为模式串去检索目标字符串.你可以使用正则表达式来查找字符串中匹 ...