OC基础回想(十一)类别

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

只是有时候子类不方便。比方,想为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 响应器的其它应用

选择器能够被传递,能够作为方法的參数使用。甚至能够作为实例变量存储。
原文地址:https://www.cnblogs.com/wzjhoutai/p/6914537.html