可以使用以下类别在目标C中扩展类:
@interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
@end
/////////////////////////////
@implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
@end
在这个小例子中,我将方法myFabulousAddition
添加到NSString。然后,我可以通过[anNSString myFabulousAddition]
调用它,就像它是NSString方法集的一部分一样。非常有用。
在Apple documents regarding Categories中,文档声明:
数量没有限制 您可以添加到的类别 class,但每个类别名称必须是 不同,每个都应该声明和 定义一组不同的方法。
如果您有类似的内容怎么办:
@interface NSString (CategoryName)
-(NSString *)myFabulousAddition; // a fabulous additional method
@end
@interface NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition; // a DIFFERENT fabulous additional method
// BUT with same name as the other category
@end
/////////////////////////////
@implementation NSString (CategoryName)
-(NSString *)myFabulousAddition {
// do something fabulous...
}
@end
@implementation NSString (ANOTHERCategoryName)
-(NSString *)myFabulousAddition {
// do something equally fabulous, but DIFFERENT...
}
@end
括号中缺少名称表示该表单是类的扩展名,如下所示:
@interface MyObject () // No name -- an extension vs category to MyObject
- (void)setNumber:(NSNumber *)newNumber;
@end
类别名称对编译器或链接器有什么意义吗?无论如何,类别名称是方法签名的一部分还是原始命名空间的一部分?如果类别名称没有意义,那么您如何知道是否要踩踏另一种方法并获得未定义的行为?
答案 0 :(得分:7)
避免踩踏方法的方法是在类别方法名称前加上前缀,如下所示:
@interface NSString (MyCompanyCategoryName)
- (NSString *)MYCO_fabulousAddition;
@end
如果您遇到来自不同类别的方法名称的冲突,那么哪一个胜出'在运行时完全没有定义。
类别的名称几乎完全没用,除了无名类别(即()
)是为类扩展保留的。类扩展的方法应该在类中实现。主@implementation
。
答案 1 :(得分:3)
类别名称并不意味着什么特别,它只是一个标识符。除非链接器(或运行时加载器)决定向您发出警告,否则无法判断多个类别是否定义了相同的方法。
答案 2 :(得分:1)
这种行为(很大程度上)是不可预测的 - 其中一个类别会胜出,但你无法分辨出哪一个。另外,我认为你很可能会从一个实现开始,最后得到另一个实现(如果在第一个类之后加载第二个类别)。
答案 3 :(得分:1)
从程序员的角度来看,它肯定是一个标识符。在编译器的观点中,类别方法只是作为类的扩展(它从中扩展)添加,而不管名称如何。
是的,您可以添加具有相同标识符的同一类的类别,即使具有相同的功能。但是你绝对不能覆盖任何函数,因为一旦你定义了类,它就只是类的一部分(就像你不能从该类中覆盖类的函数一样)。
由于它们是在运行时添加的,因此它们不会引发任何错误,只有在运行时编译器才会选择该函数,这是完全不可预测的。
答案 4 :(得分:0)
另一方面,你的问题非常有效......你不知道你是否覆盖了一种方法。如果你在同一个项目中,那么编译器会发出一个警告(或者一个错误?我不记得了),但是如果你从一个库中覆盖一个方法,那么......你运气不好......