Objective-C中的类别与扩展

类别(category)

category可以理解为给一个类“打补丁”的方法。它可以在不创建子类且不访问类原有源代码的前提下,给已有的类添加新的方法。
类别同样由接口和实现两部分组成,接口部分语法如下:

@interface 已有类 (类别名)
//方法定义
...
@end

实现部分语法如下:

@implementation 已有类 (类别名)
//方法实现
...
@end

如下程序,为NSNumber类添加加减乘除方法并进行了测试。

#import <Foundation/Foundation.h>

//为NSNumber定义一个名为fk的类别
@interface NSNumber (fk)
- (NSNumber*) add: (double) num2;
- (NSNumber*) substract: (double) num2;
- (NSNumber*) multiply: (double) num2;
- (NSNumber*) divide: (double) num2;
@end 

//为类别fk提供实现部分
@implementation NSNumber (fk)
    - (NSNumber*) add: (double) num2{
        return [NSNumber numberWithDouble:([self doubleValue] + num2)];
    }
    - (NSNumber*) substract: (double) num2{
        return [NSNumber numberWithDouble:([self doubleValue] - num2)];
    }
    - (NSNumber*) multiply: (double) num2{
        return [NSNumber numberWithDouble:([self doubleValue] * num2)];
    }
    - (NSNumber*) divide: (double) num2{
        return [NSNumber numberWithDouble:([self doubleValue] / num2)];
    }
@end

int main(int argc, char* argv[]){
    @autoreleasepool{
        NSNumber* myNum = [NSNumber numberWithInt:3];
        NSNumber* add = [myNum add:2.4];
        NSLog(@"%@", add);
        NSNumber* substract = [myNum substract:2.4];
        NSLog(@"%@", substract);
        NSNumber* multiply = [myNum multiply:2.4];
        NSLog(@"%@", multiply);
        NSNumber* divide = [myNum divide:2.4];
        NSLog(@"%@", divide);
    }
}

一般习惯将类别的接口文件命名为类名+类别名.h,对应的实现文件命名为类名+类别名.m的形式。

类别通常有如下三种用法:

  1. 利用类别对类进行模块化设计。
  2. 利用类别来调用私有方法。
  3. 利用类别来实现非正式协议。

利用类别对类进行模块化设计

通常,将一个类的接口部分放在一个.h文件里,实现部分放在一个.m文件。但如果某个类非常大时,其所有的实现部分代码放在一个.m文件将导致这个文件非常大,维护不方便。针对这种情况,可以使用category将庞大的类模块化,把不同的部分放在不同的.m文件里,提高可维护性。

利用类别来调用私有方法

定义类时,没有在接口部分定义而是直接在类实现部分定义的方法相当于私有方法,通常不允许被调用。但是,Objective-C并没有真正意义上的私有方法,调用这些方法有两种方法:

  1. 通过NSObject的performSelector:方法来执行动态调用;
  2. 通过类别来定义前向引用,从而实现对私有方法的调用。

方法1会完全避开编译器的语法检查,不见得是一种好的做法。

@interface FKItem : NSObject
@property (nonatomic, assign) double price;
@end

@implementation FKItem
- (double) calDiscount:(double) discount{
    return self.price * discount;
}
@end

如上程序,calDiscount:方法就是Objective-C中所谓的私有方法,直接通过FKItem对象调用该方法会导致错误。

为了能正确调用这个方法,可以在main()函数前增加如下类别定义:

@interface FKItem (fk)
- (double) calDiscount:(double) discount;
@end

类别的方法并不强制程序去实现它。(实际上,FKItem类的实现部分已经实现了该方法。)
这样就可以通过FKItem的对象调用这个方法了。

扩展(Extension)

扩展相当于匿名类别。定义扩展的语法格式如下:

@interface 已有类 ()
{
    实例变量
}
// 方法定义
...
@end

类别与扩展的区别

类别扩展
有名匿名
通常有单独的.h.m文件通常有单独的.h文件,而实现由类实现部分同时实现类接口和扩展中定义的方法
用于为现有类添加新方法,不允许额外定义实例变量,也不可用@property合成属性可以额外增加实例变量,也可用@property合成属性
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客熊猫GeekPanda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值