分类和扩展
此文章翻译自苹果官方文档原文地址:http://developer.apple.com/TP30001163-CH12-SW1
分类和扩展
分类允许你向一个已有的类添加方法即使你没有这个类的源代码。分类的强大功能就在于它让你可以不使用子类而拓展一个类的功能。使用分类,你还可以将一个类的实现分布在几个不同的文件中。类扩展同分类类似,但是允许在@interface以外的地方为类声明API。
给类添加方法
你可以在一个类的接口文件中的分类名下为类声明方法,同时在实现文件中相同方法名下实现他们。一个分类名代表了为一个类声明的一些方法而不是一个新类。但是,分类不能为一个类声明新的实例变量。
分类添加的方法会成为类类型的一部分。例如,在一个分类中为NSArray添加的方法在编译器编译一个NSArray实例时会被一起编译。而通过子类为NSArray类添加的方法则不会被编译到NSArray的实例中。(仅对静态指定类型的类有效因为只有静态指定类型时编译器才能知道一个对象的类类型。)
分类中的方法同类中定义的方法一样。在运行时,他们没有任何区别。通过分类添加的方法同样可以被子类继承。
分类的声明同一个类接口的声明非常相似——不同的是分类名要写在类名后面的一对括号内并且没有超类的声明。类的分类必须要引用类的接口文件,除非他的方法不访问类的任何实例变量:
#import "ClassName.h" @interface ClassName ( CategoryName ) // method declarations @end
需要注意:分类不能为类声明额外的实例变量;声明的仅仅是方法。但是类所声明的实例变量同时在分类中也同样可以使用即使是@private类型的变量。
可以为一个类声明多个分类数量没有限制,但是每个分类名字必须不同,并且每个分类中都可以定义不同的一组方法。
扩展
类的扩展就像是匿名的分类,不同是是扩展中声明的方法必须在相关类的@implementation中实现。在 Clang/LLVM 2.0 编译器中,你还可以在扩展中声明属性和实例变量。
扩展经常用于将一个已声明的只读私有属性重新声明为读写:
@interface MyClass : NSObject @property (retain, readonly) float value; @end // Private extension, typically hidden in the main implementation file. @interface MyClass () @property (retain, readwrite) float value; @end
注意扩展和分类不同在,如第二段代码中@interface后面的括号中不用指定名字。
扩展还经常用于另一种情况:一个类先公开声明一个API,然后类通过扩展再定义一些私有的方法。类扩展允许你在主类的 @interface以外的地方为类声明一些必要的方法,例如:
@interface MyClass : NSObject - (float)value; @end @interface MyClass () { float value; } - (void)setValue:(float)newValue; @end @implementation MyClass - (float)value { return value; } - (void)setValue:(float)newValue { value = newValue; } @end
setValue:方法必须在@implementation中实现(不能在分类中实现)。如若不然,编译器会报出一个警告:没有找到 setValue:方法的定义。
欢迎交流讨论。转载请注明出处。本文地址: http://www.sjslibrary.com/?p=254