Objective-C的类别(Category)与类扩展(Extension)

0x01 什么是类别

类别(Category)是Objective-C语言的一个特性。

可以在不改变类名和原来类的实现的前提下,实现对类的方法扩展。

 

0x02 创建类别

类别的声明

类别的声明看起来非常像类的声明,但在类的名称之后是写在括号内的类别名称。

@interface NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber;
@end // NumberConvenience

1、只要保证类别名称唯一,我们可以向一个类中添加任意数量的类别;

2、类别不能添加新的实例变量;

3、类别可以添加属性,而且属性必须是@dynamic类型的。意味着我们可以通过点表达式来访问setter / getter方法。

 

类别的实现

类别的实现和类的实现非常相似:

@implementation NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber
{
    NSUInteger length = [self length];
    return ([NSNumber numberWithUnsignedInt:length]);
} // lengthAsNumber
@end // NumberConvenience

 

类别的优势

在Cocoa中,类别主要有三个用途:

1、类别支持开发人员针对自己构建的类,把相关的方法分组到多个单独的文件中,对于大型而复杂的类,这有助于提高可维护性,并简化单个源文件的管理;

2、创建对私有方法的前向引用。如果编译器发现我们调用对象的某个方法,却没能找到该方法的声明或定义,便会产生警告。只要在类别中声明一个方法,编译器就不会警告了。这就是Cocoa中没有严格意义上的私有方法。但Apple并不允许应用程序访问类中的私有变量和方法,所以这条不展开详述;

3、向对象添加非正式协议(Informal Protocol)。

 

类别的缺陷

1、无法向现有的类中添加新的实例变量(类别没有空间容纳实例变量);

2、方法名称冲突,即类别中的新方法的名称与现有类中方法名称重名,类别具有更高的优先级。类别中的方法将完全取代现有类中的方法(再也无法访问现有类中的同名方法),可以考虑给类别中的方法加前缀。

 

0x03 类扩展

类扩展的声明

类别只能增加方法,不能增加实例变量,但使用类扩展(Class Extension)可以做到。

类扩展也叫匿名类别,就是不需要指定类别名字。

功能就是为一个类添加额外的原来没有的变量、方法或者合成属性:

@interface Things ()
{
  NSInteger thing4;
}
@property (readwrite, assign) NSInteger thing2;
@property (assign) NSInteger thing3;
@end

 

类扩展的实现

一般类扩展都是写在.m文件中,不单独建立一个扩展文件,如下:

#import "MyViewController.h"

// 此乃本类的扩展
@interface MyViewController ()
// 在此声明方法,添加成员变量和属性
@end

@implementation MyViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

单独生成一个类扩展文件也可以,但必须将类扩展的.h文件包含进本类的.m文件中。

 

类扩展的优势

1、能为某个类附加额外的属性,成员变量和方法声明,只是该实例变量默认是@private类型的(作用范围只能在自身类,而不是子类或其他地方);

2、有时我们需要声明一个@property,它对外是只读的(readonly),而对内是可读写的(readwrite),可以通过类扩展实现;

3、一般的私有属性和方法可以写到类扩展。

 

类扩展的缺陷

1、类扩展中添加的属性、成员变量和方法都属于私有属性和方法(只能被在本类的.m文件调用,并且这些属性和方法不能被子类继承);

2、一般类扩展都是写在.m文件中,不单独建立一个扩展文件,且必须把类扩展的@interface写在本类的@implementation的上方,否则编译器会报错; 

3、类扩展只能针对自定义的类,不能给系统类增加类扩展;

4、类扩展定义的方法必须在类的实现中进行实现(因为单独定义类扩展的话编译器只会生成一个.h文件,类扩展只能在需要扩展的类.m文件里面去进行扩展);

5、类扩展中声明的方法可以不实现,但编译器会警告(因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中);

6、单独定义类扩展的文件并且只定义属性,也需要将类实现文件中包含进类扩展文件,否则会找不到属性的setter / getter方法。

 

0x04 类别和类扩展还有继承的区别

 类别类扩展继承
功能为类添加方法,不用知道类的源码,添加变量为类添加私有变量和私有方法,在类的源文件中书写,所以知道类的源代码即能为类添加方法又能添加变量
特点

添加的方法称为类的一部分,可以被子类继承

添加的变量和方法只有这个类内部访问,正常情况下外边不能访问,不能被子类继承新添加的变量和方法只能子类才能具有,父类不具有
使用使用原始类的对象(调用-方法)或者类(调用+方法)调用方法在类内部(源文件)使用只能子类使用

 

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值