Categories VS Extensions (分类 vs 扩展)

转载翻译自:http://rypress.com/tutorials/objective-c/categories

一、Categories(分类)

     Categories是一个把单个类定义分作好几个文件的方式。它的目标是通过模块化减少代码量比较大的压力。这避免了你的代码成为1000+行的文件,这样操作和分配精确几乎是不可能的。一个好的类定义是一个独特开发者必须的。

          

     这个图是用多个文件来实现Car类。

 

           在这个模块,我们在不接触它的类原始文件的情况下,使用分类来扩展已经存在的类。我们将学到如何使用这个功能来仿生保护方法(Protected methods)。Extensions和category关联很大,一会再说。

     设置

           再我们开始试验categories时,我们需要一个类去操作,创建/改变你的已经存在的类,代码如下:

       Car.h


1

2

3

4

5

6

7

8

9

10

11

12

#import <Foundation/Foundation.h>

  

@interface Car : NSObject

  

@property(copy,nonatomic)NSString *model;

@property(readonlydouble odometer;

  

-(void)startEngine;

-(void)drive;

-(void)turnLeft;

-(void)turnRight;

@end

它的实现知识一些描述消息,因此我么可以再不同方法调用时发现。

#import "Car.h"


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@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


1

2

3

4

5

#import "Car+Maintenance.h"

  

@implementation Car (Maintenance)

  

@end  

       分类名字的约束是一个类的不同分类名字不能相同。正宗的文件命名协定是用类名+分类名。

        在Car+Maintenance.h


1

2

3

4

5

#import "Car.h"

  

@interface Car (Maintenance)

  

@end

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


1

2

3

4

5

6

7

8

9

#import "Car.h"

  

@interface Car (Maintenance)

  

-(BOOL)needsOilChange;

-(void)changeOil;

-(void)rotateTires;

-(void)jumpBatteryUsingCar:(Car *)anotherCar;

@end

     在运行的时候,他们就会成为类的一部分,尽管他们没有在一个文件中声明,你可以像访问原始文件中的方法一样去访问分类中的方法。

     当然了,你必须去实现这些方法。它的实现和原始文件实现几乎一样,除了类名称后面多了一个括号。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

#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文件导入即可,这样分类中的方法即可使用。


1

#import "Car+Maintenance.h"

如果你删除了分类,那么你就会找不到定义的方法。

  保护方法(Protected)

     但是,分类并不是简单的把类定义放到几个文件中,他是一个强大的组织工具。我们可以定义类似保护访问的修改器,方法是在一个专用的分类中,定义一个protected 接口,然后之把它导入父类实现文件中,这样就定义了保护方法,而且使它们保持隐蔽。例如我们创建Car+Protected.h,然后直接导入父类的实现文件中。


1

2

3

4

5

6

7

8

9

10

11

#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包括一个扩展.它仍是一个私有方法,扩展的语法就像一个空的分类。


1

2

3

4

#import "Car.h"

@interface Car ()

-(BOOL)engineIsWorking;

@end

     它只有一个.h文件。然后在Car.m中去实现:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

#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,扩展还可以重定义属性。这通常是用来使属性就像读写属性一样,同时保持只读到其他对象中。

     例如:


1

2

3

4

5

6

#import "Car.h"

  

@interface Car ()

@property(readwritedouble odometer;

-(BOOL)engineIsWorking;

@end

     我们可以在内部实现中指定self.odometer的值,但是再Car.m外就会编译失败。

三、总结

     分类是把类模块化道不同文件中的一种方式。扩展提供相似的功能,除了他的API必须要在主实现中公开。

      在组织大量代码库时,最常见的分类使用就是给内置数据类型(NSString 、NSArray)添加方法。这样的优点在于,你不需要去创建一个子类更新存在的代码,但是必须要小心不要去重写已经存在的方法。对于小的工程,分类完全没有必要使用,可以用协议或者子类化去实现这种功能。

时间: 2024-08-31 00:07:40

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

中小型商城系统中的分类/产品属性/扩展属性的数据库设计

声明:之所以定位在"中小型"商城系统,而非"大型"(指淘宝.拍拍这类巨无霸),理由很简单----我一直都呆在(创业型的)小公司,没见过这些大家伙是怎么设计的:)   正文: 之前发表过一篇"商城系统中[商品扩展属性]的表单生成及客户端验证",部分童鞋对于后台数据库的设计比较感兴趣,于是今天把这部分也补上.   一.产品分类设计越来越多的商城系统都热衷于选择"无限级分类"的设计,我也不例外,因为它方便扩展.这部分就不详细展开了,

yii框架分类树扩展示例_IOS

提供两种方式的分类树格式,表格和下拉框形式的树形结构可以自定义表格和下拉框的样式,自定义以哪一列的参数为格式化数据,自定义层级关系参数,自定义表格列名称,也可以设置时间的格式化. 调用方式 表格方式: 复制代码 代码如下: <?php $this->widget('ext.tree.widgets.TreeWidget',array(        'dataProvider'  => $dataProvider,           // 传递数据        'pid'      

分类(Categories)和标签(Tags)

今天网页教学网要和大家一起探讨一个网站可用性话题,那就是分类和标签的可用性问题.像博客或网络杂志这类的网站会以各种各样的方式组织和排序它们的内容以使更多的内容得到关注.按日期排序和按作者排序是网站系统通常的自动处理方式,在这两种方式基础上有两种概念来完成排序:分类(Categories)和标签(Tags).你可以同时使用这两种方法,但是可能会制造很多影响用户体验的困扰.那么你到底应该用哪种方法和为什么要用那种方法呢?让我们来一一调查这两种排列方法. 分类(Categories) 分类就像是文件夹

C# 3.0语言新特性(语言规范):2 扩展方法

规范 原文:<C# Version 3.0 Specification>,Microsoft翻译:lover_P 扩展方法(Extension Methods)是一种静态方法,可以通过实例方法的语法进行调用.从最终效果上看,扩展方法使得扩展一个现有类型和构造一个具有附加方法的类型变成了现实. 注意 扩展方法很难发觉,并且比起实例方法在功能性上有很大限制.出于这些原因,我们建议保守地使用扩展方法,仅在实例方法不大可行或根本不可行的时候才使用. 扩展成员的其他类型,如属性.事件和运算符都在考虑之中

Pentium III处理器的单指令多数据流扩展指令(1)

关键字 : Pentium,处理器,单指令多数据流扩展指令,SSE,指令集 概要 : 随着Intel Pentium III处理器的发布,给程序设计人员又带来了许多新的特性.利用这些新特性,程序员可以为用户创造出更好的产品. Pentium III和Pentium III Xeon(至强处理器)的许多新特性,可以使她能够比Pentium II和Pentium II Xeon处理器有更快的运行速度,这些新特性包括一个处理器序列号(unique processor ID)和新增SSE处理器指令集,这

什么是Java ?Java详解之扩展和相关架构

扩展和与Java程序设计语言紧密相关的架构(按字母排序). Groovy ,一种用纯Java实现的脚本语言,Python的强有力竞争者 JAIN (Java API for Integrated Networks)Java综合网络应用程序开发接口 JAI,(Java Advanced Imaging)Java进阶图像 JAXP, (Java API for XML Processing) Java XML 处理 API Java EE(原名J2EE),Java平台企业版 Java ME(原名J2

iOS 中 Base64 编解码分类实现

iOS 中 Base64 编解码分类实现 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 再补充:由此可见,当一个人极力地想要说明自已,表述清楚自已的想法的时侯,最后会被自已搞得更加不清楚了,从

obj-c编程08:分类和协议

   在第8篇文章里我们来聊聊如何扩展一个类的方法和实例变量,我们首先来看一下命名分类如何扩展一个类.在下面的代码中,首先定义一个类Player用来定义普通球员,如果第三方开发者发现普通球员缺少了一些方法,则可以用分类ext来扩充喽: 代码1:默认的Player类 Player.h文件: #import<Foundation/Foundation.h> @interfacePlayer:NSObject{ intnumber; intage; } -(void)show; -(id)init:

VMware发布大数据扩展 试图虚拟化Hadoop

VMware近日宣布,将允许用vSphere来管理Hadoop集群.这样一来,成千上万的VMware企业客户将能够使用他们已经熟悉的软件来控制Hadoop部署.从技术方面说,这提高了该公司在虚拟化基础设施运行Hadoop节点的水平,同时将虚拟化的优势带到了大数据平台. VMware日前推出了VMware vSphere Big Data Extensions(大数据扩展),这将允许该公司广受欢迎的基础设施管理软件来控制企业客户建立的Hadoop集群.该扩展仍然需要一个基础Hadoop平台,Hor