Categories VS Extensions (分类 vs 扩展)

简介:
一、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 ( readonly double  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 ( readwrite double  odometer;
-( BOOL )engineIsWorking;
@end
     我们可以在内部实现中指定self.odometer的值,但是再Car.m外就会编译失败。
三、总结
     分类是把类模块化道不同文件中的一种方式。扩展提供相似的功能,除了他的API必须要在主实现中公开。
      在组织大量代码库时,最常见的分类使用就是给内置数据类型(NSString 、NSArray)添加方法。这样的优点在于,你不需要去创建一个子类更新存在的代码,但是必须要小心不要去重写已经存在的方法。对于小的工程,分类完全没有必要使用,可以用协议或者子类化去实现这种功能。
相关文章
|
6月前
|
JavaScript 前端开发 数据处理
SAP UI5 命名空间 com.sap.vocabularies.Common.v1 的作用
SAP UI5 命名空间 com.sap.vocabularies.Common.v1 的作用
48 0
|
3月前
|
UED
使用 SAP CRM Application Enhancement Tool 创建类型为下拉菜单的扩展字段
使用 SAP CRM Application Enhancement Tool 创建类型为下拉菜单的扩展字段
28 0
|
6月前
如何通过扩展(Extension)的方式给 SAP Fiori Elements List Report 的表格新增列试读版
如何通过扩展(Extension)的方式给 SAP Fiori Elements List Report 的表格新增列试读版
38 0
|
6月前
|
API UED
SAP UI5 里 /IWBEP/VOC_COMMON 的含义和作用是什么
SAP UI5 里 /IWBEP/VOC_COMMON 的含义和作用是什么
44 0
|
Java iOS开发 C++
Objective-C类别(category)和扩展(Extension)的基本概念
Objective-C类别(category)和扩展(Extension)的基本概念
164 0
|
存储 SQL 关系型数据库
FAQ系列 | index extensions特性介绍
FAQ系列 | index extensions特性介绍
|
机器人
Robot Framework(14)- Variables 表的详细使用和具体例子
Robot Framework(14)- Variables 表的详细使用和具体例子
205 0
Robot Framework(14)- Variables 表的详细使用和具体例子
SAP SD 基础知识之行项目类别(Item Category)
SAP SD 基础知识之行项目类别(Item Category)
SAP SD 基础知识之行项目类别(Item Category)
hybris backoffice 产品属性和sample data的对应关系
hybris backoffice 产品属性和sample data的对应关系
69 0
|
容器
使用 SAP Analysis Path Framework (APF) 来展示 SAP CDS view,支持各种类型的图表显示
使用 SAP Analysis Path Framework (APF) 来展示 SAP CDS view,支持各种类型的图表显示
116 0
使用 SAP Analysis Path Framework (APF) 来展示 SAP CDS view,支持各种类型的图表显示