oc——类——类别

概述

类别,category,是对类的implementation进行模块化设计,把implementation分散到不同的模块中
  • 允许声明Method的interface:primary class interface,extension interface,category interface
  • 允许定义Method的implementation:primary class implementation,category implementation
  • category是对类的implementation进行模块化设计,把implementation分散到不同的模块中,因此在category interface中不能定义数据成员
  • category是类的接口扩展机制,可对现有类进行接口扩展,category对现有类进行接口扩展时,无法预知现有类的所有Method,因此在category中扩展Method不可避免的会与已有Method相同(SEL相同)
  • category interface和category implementation都是optional,category interface是Method声明,category implementation是Method定义
注:oc只能确保同一interface(primary class interface或extension interface)的Method声明不重复或同一implementation(primary class implementation或category implementation)的Method定义不重复

methodLists

struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
总结:
  • objc_method_list*是方法成员list,因此同一方法成员list中,方法成员名不能重名,否则编译器不能确定使用哪个方法成员,二义性错误,或者list中优先search到的方法成员屏蔽list中之后重名方法成员(ignore之后重名方法成员),oc在编译期避免此情况发生
  • methodLists类型为objc_method_list**,即方法成员list的list,methodLists(后缀s,表示复数,多个objc_method_list*)为list,其node类型为objc_method_list*(方法成员list),methodLists之所以使用objc_method_list**类型是因为类支持类别(category),primary class和每个类别(category)的方法成员list用一个objc_method_list*(方法成员list)表示,作为methodLists的一个node,methodLists至少有一个node(objc_method_list*),存储primary class的方法成员list,之后每添加一个category,就在methodLists添加一个node(objc_method_list *),存储category的方法成员list
  • methodLists作为list,学过数据结构知道,insert node时,如果insert head,时间复杂度O(1),如果insert tail,时间复杂度O(n),显然选择insert head,因此对于methodLists,起始primary class的方法成员list(objc_method_list *)是其唯一node(head),之后添加category方法成员list(objc_method_list *),insert head,因此越后编译的category,其对应方法成员list(objc_method_list *)越在methodLists前面,越先编译的category,其对应方法成员list(objc_method_list *)越在methodLists后面,primary class总是最先编译,因此primary class的方法成员list(objc_method_list *)置于methodLists tail,方法成员调用时methodLists顺序遍历,因此置于methodLists前的Method优先被search到,而primary class的方法成员list(objc_method_list *)显然最后被search到

category

@interface FBAnimal : NSObject

- (void)feedFood1:(int)food1 andFood2:(int)food2;
- (void)feedFood3:(int)food3 andFood4:(int)food4;

@end

@implementation FBAnimal

- (void)feedFood1:(int)food1 andFood2:(int)food2
{
    NSLog(@"FBAnimal+Primary feedFood1:andFood2:");
}

- (void)feedFood3:(int)food3 andFood4:(int)food4
{
    NSLog(@"FBAnimal+Primary feedFood3:andFood4:");
}

@end

@interface FBAnimal (FeedFood56)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
- (void)feedFood5:(int)food5 andFood6:(int)food6;

@end

@implementation FBAnimal (FeedFood56)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
{
    NSLog(@"FBAnimal+FeedFood56 feedFood3:andFood4:");
}

- (void)feedFood5:(int)food5 andFood6:(int)food6
{
    NSLog(@"FBAnimal+FeedFood56 feedFood5:andFood6:");
}

@end

@interface FBAnimal (FeedFood78)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
- (void)feedFood7:(int)food7 andFood8:(int)food8;

@end

@implementation FBAnimal (FeedFood78)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
{
    NSLog(@"FBAnimal+FeedFood78 feedFood3:andFood4:");
}

- (void)feedFood7:(int)food7 andFood8:(int)food8
{
    NSLog(@"FBAnimal+FeedFood78 feedFood7:andFood8:");
}

@end
- (void)use_category
{
    FBAnimal *animal = [[FBAnimal alloc] init];
    
    [animal feedFood1:1 andFood2:2];
    [animal feedFood3:3 andFood4:4];
    [animal feedFood5:5 andFood6:6];
    [animal feedFood7:7 andFood8:8];
}
output:
FBAnimal+Primary feedFood1:andFood2:
FBAnimal+FeedFood78 feedFood3:andFood4:
FBAnimal+FeedFood56 feedFood5:andFood6:
FBAnimal+FeedFood78 feedFood7:andFood8:
调换FBAnimal (FeedFood56)和FBAnimal (FeedFood78)定义顺序,本质就是调换FBAnimal (FeedFood56)和FBAnimal (FeedFood78)编译顺序,即调换FBAnimal (FeedFood56)和FBAnimal (FeedFood78)的方法成员list(objc_method_list *)插入methodLists顺序
@interface FBAnimal : NSObject

- (void)feedFood1:(int)food1 andFood2:(int)food2;
- (void)feedFood3:(int)food3 andFood4:(int)food4;

@end

@implementation FBAnimal

- (void)feedFood1:(int)food1 andFood2:(int)food2
{
    NSLog(@"FBAnimal+Primary feedFood1:andFood2:");
}

- (void)feedFood3:(int)food3 andFood4:(int)food4
{
    NSLog(@"FBAnimal+Primary feedFood3:andFood4:");
}

@end

@interface FBAnimal (FeedFood78)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
- (void)feedFood7:(int)food7 andFood8:(int)food8;

@end

@implementation FBAnimal (FeedFood78)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
{
    NSLog(@"FBAnimal+FeedFood78 feedFood3:andFood4:");
}

- (void)feedFood7:(int)food7 andFood8:(int)food8
{
    NSLog(@"FBAnimal+FeedFood78 feedFood7:andFood8:");
}

@end

@interface FBAnimal (FeedFood56)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
- (void)feedFood5:(int)food5 andFood6:(int)food6;

@end

@implementation FBAnimal (FeedFood56)

- (void)feedFood3:(int)food3 andFood4:(int)food4;
{
    NSLog(@"FBAnimal+FeedFood56 feedFood3:andFood4:");
}

- (void)feedFood5:(int)food5 andFood6:(int)food6
{
    NSLog(@"FBAnimal+FeedFood56 feedFood5:andFood6:");
}

@end
- (void)use_category
{
    FBAnimal *animal = [[FBAnimal alloc] init];
    
    [animal feedFood1:1 andFood2:2];
    [animal feedFood3:3 andFood4:4];
    [animal feedFood5:5 andFood6:6];
    [animal feedFood7:7 andFood8:8];
}
output:
FBAnimal+Primary feedFood1:andFood2:
FBAnimal+FeedFood56 feedFood3:andFood4:
FBAnimal+FeedFood56 feedFood5:andFood6:
FBAnimal+FeedFood78 feedFood7:andFood8:
如果把FBAnimal,FBAnimal (FeedFood56),FBAnimal (FeedFood78)的interface和implementation分别放于FBAnimal.h,FBAnimal.m,FBAnimal+FeedFood56.h,FBAnimal+FeedFood56.m,FBAnimal+FeedFood78.h,FBAnimal+FeedFood78.m,本质也一样,依赖于编译顺序,FBAnimal.m总是先编译,因为category依赖于primary class,而FBAnimal+FeedFood56.m和FBAnimal+FeedFood78.m的编译顺序则依赖于工程设置
FBAnimal+FeedFood56.m先编译,FBAnimal+FeedFood78.m后编译
output:
FBAnimal+Primary feedFood1:andFood2:
FBAnimal+FeedFood78 feedFood3:andFood4:
FBAnimal+FeedFood56 feedFood5:andFood6:
FBAnimal+FeedFood78 feedFood7:andFood8:
调换FBAnimal+FeedFood56.m和FBAnimal+FeedFood78.m的顺序
FBAnimal+FeedFood78.m先编译,FBAnimal+FeedFood56.m后编译
output:
FBAnimal+Primary feedFood1:andFood2:
FBAnimal+FeedFood56 feedFood3:andFood4:
FBAnimal+FeedFood56 feedFood5:andFood6:
FBAnimal+FeedFood78 feedFood7:andFood8:

总结

  • category是对类的implementation进行模块化设计,因此category interface不允许定义数据成员,允许声明Method
  • category interface和category implementation都是optional,category interface是Method声明,category implementation是Method定义
  • category数量无限制(可任意个),category对类进行扩展,且category的方法成员list(objc_method_list *)和primary class的方法成员list(objc_method_list *)及其它category的方法成员list(objc_method_list *)相互独立,因此只要确保同一category的方法成员不重复即可,允许与primary class的方法成员和其它category的方法成员重复,category常搭配extension扩展类的功能,extension负责定义数据成员和声明Method,category负责定义Method
  • category是对类的implementation进行模块化设计,把implementation分散到不同模块中,一般category interface放在头文件中对外open
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OC(Objective-C)是一种面向对象的编程语言,它支持在类中使用方法和block。类方法是在类中定义的方法,可以直接通过类名来调用,而不需要实例化对象。而block是一种闭包,可以在代码中定义并传递给方法或函数,用于延迟执行特定的逻辑。 在OC中,可以使用类方法来创建和操作类的实例,例如通过一个工厂方法创建对象,或者在类方法中实现一些与类相关的逻辑。类方法通常使用“+”符号进行声明和实现。 而block可以在方法中作为参数传递,也可以在方法中定义和使用。block可以捕获其所在作用域的变量,可以在方法内部延迟执行一段代码,也可以用于实现回调等功能。block的定义和使用使用“^(){}”语法。 类方法和block可以结合使用,例如可以在类方法中接受一个block作为参数,并在合适的时机调用该block,以实现一些灵活的逻辑。通过类方法和block的组合,可以在OC中实现更加灵活和强大的功能,例如在异步操作中使用block来回调结果,或者在工厂方法中使用block来定制对象的初始化逻辑等。 总而言之,类方法和block是OC中的两个重要特性,它们可以分别用于类的操作和延迟执行逻辑,也可以结合使用以实现更加灵活的功能。在实际的OC开发中,类方法和block通常会被广泛使用,可以帮助开发者更加简洁和灵活地实现代码逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值