OC中的分类与类扩展

2023-11-18

在OC中,对于已有的类进行扩展,我们有两种方式:

1、在原始类的定义中,进行代码扩展。

2、通过继承的方式,扩展子类。

3、使用分类的方式。

第一、二种方式不用多说,第三种方式则是OC中比较有特色的功能。

分类允许我们在不更改类的原始代码的情况下,实现对类的功能扩展,包括:添加实例方法,类方法与实例变量,属性(添加实例变量与属性需要匿名分类——类扩展)。


如何定义分类\类扩展

定义分类,很简单,只需要指出你需要扩展的类,分类名称和你要定义的分类的方法即可。其余均类似定义普通的类。形式如下

[objc]  view plain  copy
  1. @interface  要扩展的类名称(分类名称)  
  2. 。。。  
  3. @end  

分类根据有无分类名称,可以分为 分类 和 类扩展(匿名分类)。

而分类又可根据其实现方式,分为两种:

1、分别新建分类.h与分类.m文件,在独立于原始类的文件中编写分类代码。

2、在原始类文件的.h或.m中声明分类,在原始类的.m文件中实现分类。


新建.h与.m,编写类的分类

例如,我们写了一个Car类,定义如下:

[objc]  view plain  copy
  1. #import <Foundation/Foundation.h>  
  2.   
  3.   
  4. @interface Car : NSObject  
  5. @property(nonatomicstrong)NSString* name;  
  6. @property(nonatomicgetter=leftGas) NSUInteger totalGas;  
  7.   
  8. -(instancetype)initWithName:(NSString*) name;  
  9.   
  10. -(void) run;  
  11. -(void) addGas:(NSUInteger) gas;  
  12. @end  

这一个基本的Car类,让我们的汽车可以行驶(执行run方法)。但是,某天我突发奇想,想让我的汽车能够飞起来,于是我想在Car中添加fly方法,但又不想改写原始的类文件,OK,这时候就用到了类的分类,分类名称fly,定义如下:

[objc]  view plain  copy
  1. #import "Car.h"  // 注意,我们这里导入了Car.h文件,让分类知道Car类的存在  
  2.   
  3. @interface Car (Fly)  
  4. -(void) fly;  
  5. @end  

在分类的实现文件中,有如下代码来实现飞行:

[objc]  view plain  copy
  1. #import "Car+Fly.h"  
  2.   
  3. @implementation Car (Fly)  
  4.   
  5. -(void) fly  
  6. {  
  7.     NSLog(@"%@ is flying"self.name);  // 这里通过self存取方法,获得Car类的name属性值  
  8. }  
  9. @end  

上面的代码值得注意的一点是,fly函数通过self方式取得了name属性,这里其实表明分类对于类属性的访问,其实是和类本身定义一样的。(但不能够通过_name属性名称直接访问属性,否则会提示未定义)。这一点同继承不同(属性对于子类是不可见的,子类只能通过继承得到的存取方法访问属性)。

关于新建.h与.m编写新的分类,有这么几点注意:

1、分类能够像类本身一样,调用self来访问类的方法,属性。

其实将分类理解成类本身更好,因为除了声明方式不一样外,分类对原始类方法,属性,及实例方法的访问,均与类本身访问方式无二。但对于过新建.h与.m来写的分类来说,分类对于原始类的了解(即知道其中存在哪些方法,属性),仅通过原始类的接口文件(.h文件),这与在类外部方法类定义的一些内容是一样的,仅仅能够看到.h中的定义

比如,我们在原始类的.m文件中,定义了一个fire方法,而在.h文件中并没有声明该方法(fire此处为私有方法)

Car.h,没有对fire的声明

[objc]  view plain  copy
  1. @interface Car : NSObject  
  2. @property(nonatomicstrong)NSString* name;  
  3. @property(nonatomicgetter=leftGas) NSUInteger totalGas;  
  4.   
  5. -(instancetype)initWithName:(NSString*) name;  
  6.   
  7. -(void) run;  
  8. -(void) addGas:(NSUInteger) gas;  
  9. @end  

Car.m 直接实现没有声明过的fire方法,该方法在类外部不可见,但类中可以通过[self fire]形式调用 

[objc]  view plain  copy
  1. @implementation Car  
  2. ....  
  3. -(void) fire  
  4. {  
  5.     NSLog(@"%@ fire!"self.name);  
  6. }  
  7. ....  
  8. @end  

那么对于fire方法,在分类fly中是无法调用到的,若调用该方法,则会提示未定义的错误

同样的,分类对于原始类的属性的调用,仅能够通过存取方法,若直接用属性名称的话(属性名称仅在原始类的.m中可见),则会提示未定义错误

2、对于新建.h,.m分类文件,我们的命名应当遵循XCode的默认命名规则。

在Xcode中创建类的分类文件时,会默认以下面方式命名:

[objc]  view plain  copy
  1. 类名+分类名.h/.m  

例如,对于Car的fly分类,我们应该命名文件

[objc]  view plain  copy
  1. Car+fly.h  
  2. Car+fly.m  

3、在使用分类的扩展方法时,需要导入分类的.h文件,才能让执行代码知道分类扩展方法的存在。实际上,由于在分类文件中我们已经导入了原始类的头文件,所以在使用分类时,仅仅导入分类头文件即可。

4、分类能够对实例方法,类方法进行扩展,但不能够添加类的属性及实例变量。


在原始类文件的.h或.m中声明分类,在原始类的.m文件中实现分类

通过改写原始类的方式实现分类,个人感觉用处不大(这和直接改写原始类有什么区别呢?)。

在原始类中编写分类,与新建文件编写分类的区别有:

1、对于原始类的可视程度,在原始类中编写的分类是和类本身一样的(即可访问私有方法及通过属性名访问属性),这与新建文件编写的分类是不同的。


类扩展

类扩展其实是一种特殊的分类,即匿名分类,如下格式

[objc]  view plain  copy
  1. @interface Car ()  
  2. -(void) fire;  
  3. @property(nonatomic) NSUInteger price;  
  4. @end  

括号中并未给出分类名称,这种分类有个专业名称—— 类扩展

类扩展与分类的区别如下:

1、类扩展仅能够在原始类中声明(.h或.m中均可,在.m中声明的类扩展其定义的属性和方法均是私有的)

2、类扩展的实现仅能够在原始类的.m中编写。

3、在类扩展中可以扩展类的属性,而在分类中仅能够扩展实例方法和类方法。


对于类分类,有几点比较有意思:

1、对于Cocoa中的类,我们也可以进行分类扩展,特别是对于NSObjec类,我们对其扩展,那么所有的类均可以调用我们的扩展方法!

2、分类扩展可以继承。

3、对于分类或扩展中声明的方法,我们并不要必须实现,而是在必要时,才会有某个类来实现,这点和协议很像。

4、对于类中的同名方法,分类扩展会覆盖其实现。

5、对于类的私有方法,我们可以在分类扩展中将其声明为可见的(而不实现),这样在类外部就可以调用该类的私有函数了。


FROM:  http://blog.csdn.net/u013378438/article/details/44491703


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OC中的分类与类扩展 的相关文章

随机推荐

  • 手机APP远程温湿度监控系统(连上公网、阿里云)

    APP界面 实物图 操作演示 一 硬件电路图 这里有两点需要说明 1 第一点是关于LCD1602需不需要加上拉电阻的说明 51单片机P0口作为IO口输出时 输出低电平为0 输出高电平为高组态 并非5V 相当于悬空状态 也就是说P0 口不能真
  • 【蓝桥杯Python组】寻找2020

    寻找2020 题目描述 小蓝有一个数字矩阵 里面只包含数字 0 和 2 小蓝很喜欢 2020 他想找到这个数字矩阵中有多少个 2020 小蓝只关注三种构成 2020 的方式 同一行里面连续四个字符从左到右构成 2020 同一列里面连续四个字
  • matlab中 hold on 与 hold off,figure作用

    hold on是当前轴及图像保持而不被刷新 准备接受此后将绘制的图形 多图共存 即启动图形保持功能 当前坐标轴和图形都将保持 从此绘制的图形都将添加在这个图形的基础上 并自动调整坐标轴的范围 hold off使当前轴及图像不再具备被刷新的性
  • moviepy音视频剪辑:视频剪辑基类VideoClip详解

    前往老猿Python博文目录 一 概述 在 moviepy音视频剪辑 moviepy中的剪辑基类Clip详解 和 moviepy音视频剪辑 moviepy中的剪辑基类Clip的属性和方法详解 介绍了剪辑相关类及类关系 可以看到视频剪辑类Vi
  • 汽车电子行业静态分析和代码审查规则

    汽车电子行业静态分析和代码审查规则 查了很多编码规则大都是PDF版 最终我整理出了几份word版的 并且帮大家排版好了可直接用于书写测试大纲或报告 下载链接在我的下载中 规则包含以下 1 MISRA C 2012 2 MISRA C 200
  • Node.js入门 03:模块化规范 CommonJS 与 ES Module

    文章目录 目的 CommonJS 基础使用 module 对象 require 方法 ES Module 混合使用 总结 目的 传统的用在网页中的JavaScript代码文件与文件之中的内容都是全局相互可见的 这对于大型项目特别是多人合作的
  • 领域驱动设计:DDD分层架构

    文章目录 DDD 分层架构 DDD 分层架构最重要的原则 DDD 分层架构推动架构演进 三层架构如何演进到 DDD 分层架构 微服务架构模型有好多种 例如整洁架构 CQRS 和六边形架构等等 每种架构模式虽然提出的时代和背景不同 但其核心理
  • 近一月翻阅资料小结

    近一个月接触的东西比较多 梳理一下 Nginx Tomcat 实现负载均衡 同时采用keepalived的形式实现HA 负载后 关键问题就是session共享的问题 可实现的思路较多 Tomcat6以后本身可以使用cluster技术达成 也
  • 训练自己的ai模型(三)学习笔记与项目实操(一些概念理解杂谈)

    ai模型大火 作为普通人 我也想做个自己的ai模型 训练自己的ai模型通常需要接下来的的六步 一 收集和准备数据集 需要收集和准备一个数据集 其中包含想要训练模型的数据 这可能需要一些数据清理和预处理 以确保数据集的质量和一致性 二 选择和
  • PTA——7-3 两个数的简单计算器

    输入格式 输入整数A 符号ch和整数B 输出格式 根据符号ch 在一行中输出A ch B的值 如果ch是 则输出A B的值 如果ch是 则输出A B的值 如果ch是 则输出A B的值 如果ch是 则输出A B的值 题目保证B不为0 并且结果
  • C++泛型编程:源起、实现与意义

    C 泛型编程 源起 实现与意义 为什么泛型泛型编程 Generic Programming 最初提出时的动机很简单直接 发明一种语言机制 能够帮助实现一个通用的标准容器库 所谓通用的标准容器库 就是要能够做到 比如用一个List类存放所有可
  • [Linux]日志文件已删掉磁盘空间不释放,不重启服务进程的解决方法

    Linux 日志文件已删掉磁盘空间不释放 不重启服务进程的解决方法 问题背景 服务进程启动后 后台会有写日志的操作 当服务进程还没停掉 日志就会一直在写 这时候手动删除日志 会造成日志在linux该目录下已经删除 但是磁盘空间不会被释放掉
  • C语言函数操作大全----(超详细)

    fopen 打开文件 相关函数 open fclose 表头文件 include
  • MAC电脑常用效率工具推荐

    作者主页 IT技术分享社区 作者简介 大家好 我是IT技术分享社区的博主 从事C Java开发九年 对数据库 C Java 前端 运维 电脑技巧等经验丰富 个人荣誉 数据库领域优质创作者 华为云享专家 阿里云专家博主 个人博客 IT技术分享
  • supervisor系列:3、配置文件

    supervisor系列 3 配置文件 文章目录 supervisor系列 3 配置文件 1 文件格式 1 1 环境变量 2 unix http server 段设置 2 1 unix http server 段的值 2 2 unix ht
  • VS中Qt中ui文件和生成.h文件问题

    vs中的ui的ui xxxx h头文件是由Qt通过编译生成 vs项目属性中配置环境调用Qt安装目录下bin目录下的uic exe来自动生成代码 如果移动工程目录 而之前又把相关的ui xxx h头文件添加到工程或移动其位置 那么再次修改ui
  • sketchup 255个su常用插件)_「教程」巧用Rhino和SU,做出你想要的地形效果

    Xiao素材 地形建模教程 本期精选 教你如何做好地形效果图 1 SU部分 地形效果 SU插件安装小教程 su软件是我们现在经常会使用到的一个软件 但是在我们作图的过程中会发现 很多情况下 相对于一些复杂的图形我们需要依赖相关的插件 比如
  • python递归函数代码_Python递归函数 二分查找算法实现解析

    一 初始递归 递归函数 在一个函数里在调用这个函数本身 递归的最大深度 998 正如你们刚刚看到的 递归函数如果不受到外力的阻止会一直执行下去 但是我们之前已经说过关于函数调用的问题 每一次函数调用都会产生一个属于它自己的名称空间 如果一直
  • Kubernetes + Dashboard 集群搭建

    1 环境说明 基于kubeadm工具部署k8s 集群 还有基于二进制的部署方式但是需要单独部署k8s的每个组件比较繁琐 kubeadm是 Kubernetes官 提供的 于快速部署Kubernetes集群的 具 基于Kubernetes v
  • OC中的分类与类扩展

    在OC中 对于已有的类进行扩展 我们有两种方式 1 在原始类的定义中 进行代码扩展 2 通过继承的方式 扩展子类 3 使用分类的方式 第一 二种方式不用多说 第三种方式则是OC中比较有特色的功能 分类允许我们在不更改类的原始代码的情况下 实