一、分类(类别/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

分类(类别/Category)与 类扩展(Extension)的更多相关文章

  1. 分类(Category)的本质 及其与类扩展(Extension) /继承(Inherit)的区别

    1.分类的概念 分类是为了扩展系统类的方法而产生的一种方式,其作用就是在不修改原有类的基础上,为一个类扩展方法,最主要的是可以给系统类扩展我们自己定义的方法. 如何创建一个分类?↓↓ ()Cmd+N, ...

  2. iOS分类(category),类扩展(extension)—史上最全攻略

    背景: 在大型项目,企业级开发中多人同时维护同一个类,此时程序员A因为某项需求只想给当前类currentClass添加一个方法newMethod,那该怎么办呢? 最简单粗暴的方式是把newMethod ...

  3. 类目(category) - 类扩展(extension) 区别

    说明: 方法,属性或变量:   类别只能添加方法,不能添加属性(理论上,但可以通过runtime的关联添加). 扩展可以添加方法和实例变量或属性,实例变量默认@private类型.扩展是类别的一个特例 ...

  4. 关于iOS 类扩展Extension的进一步理解

    很多人可能会问  iOS的分类和扩展的区别,网上很多的讲解,但是一般都是分类讲的多,而这也是我们平常比较常用的知识:但是,对于扩展,总觉得理解的朦朦胧胧,不够透彻. 这里就讲一下我自己的理解,但是这个 ...

  5. 类扩展Extension

    延展(Extension):在本类里声明私有方法. 1:延展定义的方法是在implemetation中. 2:声明的方法是私有方法. 3:延展中声明的方法可以不实现. #import "Ho ...

  6. iOS中 分类(category)与扩展(Extension)的区别?

    1.分类(category)的作用 (1).作用:可以在不修改原来类的基础上,为一个类扩展方法.(2).最主要的用法:给系统自带的类扩展方法. 2.分类中能写点啥? (1).分类中只能添加“方法”,不 ...

  7. OC分类(类目/类别) 和 类扩展 - 全解析

    OC分类(类目/类别) 和 类扩展 - 全解析   具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...

  8. OC-ARC,类扩展,block

    总结 标号 主题 内容 一 autorelease autorelease基本概念/自动释放池/autorelease基本使用 二 autorelease注意事项 注意点/应用场景 三 ARC 什么是 ...

  9. iOS中的分类(category)和类扩展(extension)

    今天在研究swift的时候看到了分类和扩展.这是两个十分重要有用的功能,但是之前用的不多,没有深入了解过,在今天就从头理一遍. 一.分类(Category): 概念: 分类(Category)是OC中 ...

随机推荐

  1. Spring 之定义切面尝试(基于注解)

    [Spring 之定义切面尝试] 1.标记为深红色的依赖包是必须的 <dependency> <groupId>org.springframework</groupId& ...

  2. 【c++ primer, 5e】访问控制与封装

    练习 7.16 无,类的接口定义在public说明符之后,类的实现细节定义在private说明符之后. 7.17 有.类成员的默认访问权限不同.class的类成员默认为private,struct的则 ...

  3. MySQL-5.7 存储过程及函数

    1.语法 CREATE [DEFINER = { user | CURRENT_USER }] PROCEDURE sp_name ([proc_parameter[,...]]) [characte ...

  4. jQuery垂直滑动切换焦点图

    在线演示 本地下载

  5. shell-一些有趣的使用

    1. 对字符串进行MD5加密  echo test |md5sum|awk '{print $1}' 字符串数量很多时可以这样做: echo test |md5sum|awk '{print $1}' ...

  6. 完全理解Android中的RemoteViews

    一.什么是RemoteViews RemoteViews翻译过来就是远程视图.顾名思义,RemoteViews不是当前进程的View,是属于SystemServer进程.应用程序与RemoteView ...

  7. python 获取探针页面,自动查询公司出口

    在一些渗透当中,我们需要批量探针出口来达到我们的目的. 所以就有了这个丑陋简洁的小脚本. #!/usr/bin/env python #-*- coding:utf- -*- import sys i ...

  8. 带你彻底明白 Android Studio 打包混淆

    前言 在使用Android Studio混淆打包时,该IDE自身集成了Java语言的ProGuard作为压缩,优化和混淆工具,配合Gradle构建工具使用很简单.只需要在工程应用目录的gradle文件 ...

  9. css字体介绍

    内容一切来自百度百科 1.Helvetica Helvetica是一种被广泛使用的的西文字体,于1957年由瑞士字体设计师爱德华德·霍夫曼(Eduard Hoffmann)和马克斯·米耶丁格(Max ...

  10. spring:设置映射访问路径 或 xml配置访问路径 (spring mvc form表单)

    项目hello, 在src/main/java下面建一个目录: charpter2 一.xml配置访问路径 web.xml <web-app> <display-name>Ar ...