在编写面向对象的程序时,常常要为现有的类加入一些新的行为,通常採用创建子类的方法。

只是有时候子类不方便。比方,想为NSString类加入一个新的行为,可是NSString实际上仅仅是一个类簇的表面形式,因而为这种类创建子类会很困难。

利用Objective-C的动态执行时机制,能够使用类别(category)来为现有的类加入新方法。


1.创建类别

通常类别代码放在独立的文件里,以“类名称+类别名称”的风格命名。

1.1開始创建

打开项目,在导航栏中选择你想让文件出现的群组。选择File-》New-》New File选项,或者快捷键Command+N,在弹出的新文件窗体的左側选择 iOS-》Source,在右側选择Objective-C File图标。点击Next:


在File一栏中输入类别的名称,选择File Type为Category,在Class中选择想要加入方法的类:


1.2 @interface部分

类别的声明看起来很像类的声明:
@interface NSString (NumberConvenience)
-(NSNumber *)lengthAsNumber;
@end//NumberConvenience

注意:
1)仅仅要保证类别名称唯一,就能够向一个类中加入随意数量的类别。

2)能够在类别中加入属性,可是不能加入实例变量。并且,属性必须是@dynamic类别的。加入属性的优点是,你能够通过点表达式来訪问setter和getter方法。


1.3 @implementation 部分

代码:
@implementation NSString (NumberConvenience)
-(NSNumber *)lengthAsNumber
{
NSUIngeter length = [self length];
return ([NSNumber numberWithUnsignedInt:length]);
}//lengthAsNumber
@end // NumberConverience

1.4 类别的缺陷

1)无法向类中加入新的实例变量,类别没有空间容纳实例变量。
2)名称冲突。也就是类别中的方法和现有的方法重名。当发生名称冲突时,类别具有更高的优先级。导致初始方法不再可用。有些编程人员会在类别方法名中加入一个前缀。以确保不会发生名称冲突。
说明:
也有一些技术能够克服类别无法添加新实例变量的局限。

比如,使用全局字典来存储对象和你想要关联的额外变量之间的映射。

但此时须要认真考虑一下,类别是否是完毕当前任务的最佳选择。


1.5 类别的优势

     在Cocoa中,类别主要有三个用途:将类的实现代码分散到多个不同文件或框架中,创建对私有方法的前向引用。以及向对象加入非正式协议(informal protocol)。
     利用类别能够将一个类的代码,依照不同的用途。分散到多个不同的源文件里。还能够分散到多个不同的框架中。比如。尽管NSString类是在Foundation框架中声明的,可是AppKit中有一个NSString的类别,称为NSStringDrawing。该类别同意你向字符串发送画图消息。Cocoa的设计人员通过类别使数据功能放在Foundation框架中,而画图功能放在AppKit框架中。

1.6 类扩展

类扩展就像是没有命名的类别。
一个类MyClass类的声明:
@interface MyClass:NSObject
@property (retain, readonly) float value;
@end

类MyClass的扩展:
@interface MyClass()
@property (retain, readwrite) float value;
@end

特点:
1)类扩展不须要名字
2)能够在你的类中使用它
3)能够加入实例变量
4)能够将仅仅读权限改成可读写的权限
5)创建数量不限

使用场景:
某些情况,我们须要声明一个@property。它对外是仅仅读的(readonly),而对内是可读写的(readwrite),这时。能够通过扩展来实现。



2. 通过类别创建前向引用

假设其他类中的方法未实现,在你訪问其他类的私有方法时编译器会报错。这时,使用类别,在类别中声明这些方法(不必提供方法实现),编译器就不会再产生警告。

3.非正式协议和托付类别

3.1 托付

Cocoa中的类常常使用一种名为托付(delegate)的技术。
托付是一种对象,还有一个类的对象会要求托付对象运行它的某些操作。

3.2 托付和类别

托付+类别的一种应用:创建一个非正式协议。
通过创建非正式协议,将一些方法声明为NSObject的类别。方法的实现能够发送给不论什么对象,不管这些对象实际上属于哪一个类。

这也意味着。仅仅要一个类加入了这个NSObject类别的头文件。这个对象就成为了一个托付对象。能够调用类别中声明的方法。

比如:
1)以下建立一个NSObject的类别:NSObject+MyDelegateMethods


2)在NSObject+MyDelegateMethods的头文件里声明一个方法:method


在implementation文件里实现这种方法:


在还有一个类中使用这个NSObject类别中的方法:


3.3 响应选择器

NSObject提供了一个名为respondesToSelector:的方法。该方法询问对象以确定其是否可以响应某个特定的消息。
为了确保托付对象是否能响应消息。NSObject+MyDelegateMethods须要调用respondsToSelector:@selector(method)。

假设该托付对象响应给定的消息,则向该托付对象发送该消息。否则将临时忽略该托付对象。继续正常执行。



3.4 响应器的其它应用

选择器能够被传递,能够作为方法的參数使用。甚至能够作为实例变量存储。

OC基础回想(十一)类别的更多相关文章

  1. OC基础回想(十二)协议

    在OC基础(十一)中我们讨论了类别和非正式协议的奇异之处.在使用非正式协议时.能够仅仅实现你想要获得响应的方法.也不必在对象中声明不论什么内容来表示该对象可用作托付对象. 全部这些任务能够用最少的代码 ...

  2. Bootstrap <基础三十一>插件概览

    在前面布局组件中所讨论到的组件仅仅是个开始.Bootstrap 自带 12 种 jQuery 插件,扩展了功能,可以给站点添加更多的互动.即使不是一名高级的 JavaScript 开发人员,也可以着手 ...

  3. Bootstrap <基础二十一>徽章(Badges)

    Bootstrap 徽章(Badges).徽章与标签相似,主要的区别在于徽章的边角更加圆滑. 徽章(Badges)主要用于突出显示新的或未读的项.如需使用徽章,只需要把 <span class= ...

  4. 【OC基础语法考试】

    OC基础语法已经全部学完,但是这些知识只是最基础的,还有很多高级知识,这个可能需要后面慢慢的去学习才能体会到.接下来我会总结前面的OC基础语法,如果大家发现有什么不正确的地方,请指正,小弟是新生,多请 ...

  5. iOS 阶段学习第11天笔记(OC基础知识)

    iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import  用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...

  6. OC基础笔记目录

    OC基础(1) Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 OC基础(2) 类与对象 类的设计 第一个OC类 对象方法的声明和实现 类方法的声明和实现 OC基础(3) 对象 ...

  7. OC基础 文件管理

    OC基础  文件管理 1.文件管理类NSFileManager对象的创建: NSFileManager *fm = [NSFileManager defaultManager]; 2.文件操作: (1 ...

  8. OC基础 NSDate

    OC基础  NSDate #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @auto ...

  9. OC基础 NSData

    OC基础 NSData 1.NSString转NSData //NSString转NSData NSString *string = @"abcd12345"; NSData *d ...

随机推荐

  1. mysql数据的操作

    一.插入数据记录 1.插入完整数据记录 INSERT INTO table_name VALUES(value1,value2......valuen); 2.插入数据记录的一部分 INSERT IN ...

  2. D3.js 力导向图(小气泡围绕中心气泡)

    html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3 ...

  3. [ Nowcoder Contest 165 #D ] 合法括号序列

    \(\\\) \(Description\) 键盘上有三个键,敲击效果分别是: 在输出序列尾部添加一个左括号 在输出序列尾部添加一个右括号 删除输出序列尾部的第一个元素,若输出序列为空,则什么都不发生 ...

  4. 从JavaScript的单线程执行说起

    先看一段代码: 1 2 3 4 5 setTimeout(function(){     alert("a"); }, 0); while(1); alert("b&qu ...

  5. Python标准库os

    如果你希望自己的程序能够与平台无关的话,这个模块至关重要. os.name #'nt' for windows, 'posix' for linux/unix os.getcwd() #get cur ...

  6. Detectron-MaskRCnn: 用于抠图的FCNN

    市面上暂时还没有找到可以在消费机显卡上实时运行的MaskRCnn,TensorFlow即使是C++版本训练在coco数据集上的模型也是慢的要死,最后不堪忍受,只能放弃. 经历了一些列fuckingDo ...

  7. Escaping Closures 两点:本质是生命周期标示符

    1.block需要(拷贝)保存: 2.block引用的环境变量需要处理. 相当于oc中的copy block. Escaping Closures A closure is said to escap ...

  8. C# 调用指定打印机 (并不是默认)

    this.printDocument1.PrinterSettings.PrinterName = "Microsoft XPS Document Writer"; this.pr ...

  9. Oracle 函数总结

    <1>=========================返回 String,其中包含有与指定的字符代码相关的字符======================== 函      数:< ...

  10. redis查看数据

    目前Redis缓存数据库在许多行业平台大量应用,有效解决了高并发等特定场景的应用性能瓶颈,Redis数据的查看.维护,性能监控有没有好用的工具呢,目前TreeSoft数据库管理系统可以满足实现需求. ...