OC中类别、扩展、协议与委托

本文深入探讨了 Objective-C 中的类别、扩展和协议的概念与应用,包括如何通过类别动态扩展类功能,如何使用扩展临时扩展类并添加额外属性与方法,以及如何利用协议实现多继承和委托机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类别(category)——通过使用类别,我们可以动态地为现有的类添加新方法,而且可以将类定义模块化地分不到多个相关文件中。通常只在类别中定义方法。

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. 类别,接口部分的定义,通常该文件命名为已有"类+类别名.h"  
  2. @interface 已有类 (类别名)  
  3. //.......方法实现  
  4. @end  
例如,考虑为NSNumber增加一个类别,则接口部分代码如下
[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #import <Foundation/Foundation.h>  
  2. @interface NSNumber (code)  
  3. @end  

该类别的实现部分如下

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #import "NSNumber+code.h"  
  2.   
  3. @implementation NSNumber (code)  
  4. -(NSNumber *) add:(double) num  
  5. {  
  6.     return [NSNumber numberWithDouble:([self doubleValue] +num)];  
  7. }  
  8. -(NSNumber *) mult:(double) num  
  9. {  
  10.     return [NSNumber numberWithDouble:([self doubleValue] +num)];  
  11. }  
  12. @end  


[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. 所有NSNumber类的实例就都会具有add:、multi:方法,从而实现对NSNumber类的动态扩展。  

我们知道,如果一个函数在.h文件中无声明而在.m文件中定义它的实现,那么该方法就是私有方法,只能在本类的文件中使用。若我们在类别的接口部分声明这个方法,那么我们就可以实现对该私有方法的访问。

—————————————————————————————————————————————————————————————————————————————

扩展(extension)

扩展与类别相似,扩展相当于匿名类别,即没有类别名得类别

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. 类别,接口部分的定义,通常该文件命名为已有"类_xxx.h"  
  2. @interface 已有类 ()  
  3. //.......方法实现  
  4. @end  

在用法上,类别通常都都有单独的.h和.m文件。扩展则是临时的对某个类进行扩展,类的实现部分同时实现类接口部分定义的方法和扩展中定义的方法。定义类的扩展时,可以增加额外的实例变量,也可使用@property和@synthesize关键字,但在定义类的列表时不允许额外定义实例变量。

有类名为Vehicle,只有name属性没有定义方法。对其进行扩展

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #import "vehicle.h"  
  2. @interface Vehicle ()  
  3. @property(nonatomicstrongNSString *color;  
  4. -(void) drive:(NSString *)name;  
  5. @end  
为原来的Vehicle类增加color属性和drive:方法,因此在Vehicle.m实现文件里面要实现Vehicle.h里声明的方法及这个drive:方法。

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. //"Vehicle.m"  
[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #import "Vehicle_ext.h"  
  2. @implementation Vehicle  
  3. -(void) drive:(NSString *)name  
  4. {  
  5.     NSLog(@"交通工具名称%@,颜色属性%@",_name,_color);  
  6. }  
  7. @end  
在实际使用中,通用的做法是省略掉Vehicle_ext.h文件,而是将其中的内容直接添加在Vehicle.m文件@implementation前部即可。

—————————————————————————————————————————————————————————————————————————————

协议(protocol)

类别(catgory)可以实现非正式协议,以NSObject为基础,为NSOject创建类别,创建类别时指定该类新增的方法,这是实现非正式协议的过程。而OC中对于实现非正式协议的类而言,OC并不强制实现该协议中的所有方法 。

正式协议使用@protocol关键字定义

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. @protocol 协议名 <父协议1, 父协议2>  
  2. {  
  3.       //.....方法声明  
  4. }  
  5. @end  
协议是支持多继承的。在OC2.0标准中新增了@required\@optional两个关键字,声明方式是必须是必须实现还是可选的,默认为@required.

遵守协议的语法如下

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. @interface 类名:父类型 <协议1, 协议2...>  

使用协议来定义变量,那么这些变量只能调用该协议中声明的方法,否则编译器会提示错误。

使用协议来定义变量的两种语法

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. NSObject<协议1,协议2..>*变量名;  
  2. id<协议1,协议2...> 变量;  

协议体现的是一种规范,定义协议的类可以把协议定义的方法委托(delegate)给实现协议的类,这样可以让类具有更好的通用性,具体的动作交给协议的实现类来完成。在大量的应用程序开发中大量依赖委托这个概念。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值