一、分类(类别/Category)

1、适用范围

     当你已经封装好了一个类(也可能是系统类、第三方库),不想在改动这个类了,可是随着程序功能的增加需要在类中增加一个方法,这时我们不必修改主类,只需要给你原来的类增加一个分类。
     将一个大型的类拆分成不同的分类,在不同分类中实现类别声明的方法,这样可以将一个类的实现写到多个.m文件中,方便管理和协同开发。
     分类中的方法可以只声明,不实现,所以在协议不支持可选方法的时候(协议现在已经支持可选方法),通常把分类作为非正式协议使用。
 
2、语法格式
     文件中的语法
@interface 主类类名(分类类名)
//不可以定义成员属性
@end @implementation 主类类名(分类类名) @end

文件名通常为:主类名+分类名

     调用方法时,只需要向主类引用发送消息即可。
 
3、注意事项

  • 分类中方法的优先级比原来类中的方法高,也就是说,在分类中重写了原来类中的方法,那么分类中的方法会覆盖原来类中的方法
  • 分类中只能声明方法,不能添加属性变量,在运行时分类中的方法与主类中的方法没有区别
  • 通常来讲,分类定义在.h文件中,但也可以定义.m文件中,此时分类的方法就变成私有方法
4、如何使用
     定义PYJViewController类的分类
     “PYJViewController+CategoryController.h”文件:
@interface PYJViewController (CategoryController)
- (void)test;
@end

“PYJViewController+CategoryController.m”文件:

@implementation PYJViewController (CategoryController)
- (void)test {
NSLog(@"这是一个分类");
}
@end

5、虽然不能在分类(类别)中定义成员属性,但是有办法也可以让它支持添加属性和成员变量

Category是Objective-C中常用的语法特性,通过它可以很方便的为已有的类来添加函数。但是Category不允许为已有的类添加新的属性或者成员变量。     
    一种常见的办法是通过runtime.h中objc_getAssociatedObject / objc_setAssociatedObject来访问和生成关联对象。通过这种方法来模拟生成属性。

“NSObject+SpecialName.h”文件:

@interface NSObject (SpecialName)
@property (nonatomic, copy) NSString *specialName;
@end

“NSObject+SpecialName.m”文件:

#import "NSObject+Extension.h"
#import <objc/runtime.h>
static const void *SpecialNameKey = &SpecialNameKey;
@implementation NSObject (SpecialName)
@dynamic specialName; - (NSString *)specialName {
//如果属性值是非id类型,可以通过属性值先构造OC的id对象,再通过对象获取非id类型属性
return objc_getAssociatedObject(self, SpecialNameKey);
} - (void)setSpecialName:(NSString *)specialName{
//如果属性值是非id类型,可以通过属性值先构造OC的id对象,再通过对象获取非id类型属性
objc_setAssociatedObject(self, SpecialNameKey, specialName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} @end

二、类扩展

1、适用范围

     扩展是分类的一种特殊形式。
 
2、语法格式
     @interface 主类类名()
     @end
     扩展通常定义在主类.m文件中,扩展中声明的方法直接在主类.m文件中实现。
 
3、注意事项
  • 扩展中可以声明实例变量,可以声明属性
  • 因为扩展通常定义在主类的.m文件中,所以扩展声明的方法和属性通常是私有的
4、分类和扩展的区别
     分类是不可以声明实例变量,通常是公开的,文件名是:主类名+分类名.h
     扩展是可以声明实例变量,是私有的,文件名为:主类名_扩展标识.h,在主类的.m文件中#import该头文件
 
5.如何使用

    定义 PYJViewController类的扩展
    方式1、以单独的文件定义
    “PYJViewController_ExtensionController.h”文件:
#import"PYJViewController.h"

@interface PYJViewController ()
@property(nonatomic, copy)NSString *stringExtension;
- (void)testExtension;
@end

方式2、在主类的.m文件中定义

    “PYJViewController.m”文件:

#import"PYJViewController.h"

@interface PYJViewController ()
@property(nonatomic, copy)NSString *stringExtension;
- (void)testExtension;
@end

在主类的.m文件中实现扩展定的方法:

@implementation PYJViewController
- (void)testExtension {
self.stringExtension = @"给扩展里面定义的属性字符串赋值";
NSLog(@"定义的属性String是:%@", self.stringExtension);
}
@end

最新文章

  1. orcale 动态执行语句
  2. PCA人脸识别
  3. 复习一下,? extends T 和 ? super T
  4. JdkDynamicAopProxy源码
  5. ASP.NET网站实现中英文转换(本地化资源)
  6. 从 ReactiveCocoa 中能学到什么?不用此库也能学以致用
  7. linux 常用find命令
  8. Gora官方文档之二:Gora对Map-Reduce的支持
  9. Envelope几何对象 Curve对象几何对象 Multipatch几何对象 Geometry集合接口 IGeometryCollection接口
  10. linux dd使用记录
  11. 数据结构 Python实现
  12. hive的map类型处理
  13. Fiddler抓包使用教程-断点调试
  14. 使用boost.python封装C++库
  15. 【练习】Python第三次
  16. Tomcat启动时项目重复加载,导致资源初始化两次!
  17. 【转载】和 Thrift 的一场美丽邂逅
  18. K8S Dashborad登陆认证文档
  19. [LeetCode&amp;Python] Problem 463. Island Perimeter
  20. HSSFWorkbook 创建Excel文件

热门文章

  1. pt-osc使用方法
  2. Apache 浏览器访问限制配置
  3. 20145222黄亚奇《网络对抗》- shellcode注入&amp;Return-to-libc攻击深入
  4. 转换数据库连接池为hikaricp
  5. 【Java并发】Executor框架
  6. Spring_事务-注解代码
  7. Spring Boot 设置启动时banner
  8. spring security采用基于简单加密 token 的方法实现的remember me功能
  9. 简单的aop实现日志打印(切入点表达式)
  10. python+senium+chrome的简单爬虫脚本