Objective-C类别名称可以做什么吗?

时间:2011-04-16 19:40:40

标签: objective-c

可以使用以下类别在目标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

类别名称对编译器或链接器有什么意义吗?无论如何,类别名称是方法签名的一部分还是原始命名空间的一部分?如果类别名称没有意义,那么您如何知道是否要踩踏另一种方法并获得未定义的行为?

5 个答案:

答案 0 :(得分:7)

避免踩踏方法的方法是在类别方法名称前加上前缀,如下所示:

@interface NSString (MyCompanyCategoryName)

- (NSString *)MYCO_fabulousAddition;

@end

如果您遇到来自不同类别的方法名称的冲突,那么哪一个胜出'在运行时完全没有定义。

类别的名称几乎完全没用,除了无名类别(即())是为类扩展保留的。类扩展的方法应该在类中实现。主@implementation

答案 1 :(得分:3)

类别名称并不意味着什么特别,它只是一个标识符。除非链接器(或运行时加载器)决定向您发出警告,否则无法判断多个类别是否定义了相同的方法。

答案 2 :(得分:1)

这种行为(很大程度上)是不可预测的 - 其中一个类别会胜出,但你无法分辨出哪一个。另外,我认为你很可能会从一个实现开始,最后得到另一个实现(如果在第一个类之后加载第二个类别)。

答案 3 :(得分:1)

从程序员的角度来看,它肯定是一个标识符。在编译器的观点中,类别方法只是作为类的扩展(它从中扩展)添加,而不管名称如何。

是的,您可以添加具有相同标识符的同一类的类别,即使具有相同的功能。但是你绝对不能覆盖任何函数,因为一旦你定义了类,它就只是类的一部分(就像你不能从该类中覆盖类的函数一样)。

由于它们是在运行时添加的,因此它们不会引发任何错误,只有在运行时编译器才会选择该函数,这是完全不可预测的。

答案 4 :(得分:0)

我相信他们没有任何意义。你并没有真正在你的代码中使用它们......因为它们是类别而且...类别的语义......只是为了对某些东西进行分类,我认为这有点合乎逻辑...... 我会说他们只是收集方法......

另一方面,你的问题非常有效......你不知道你是否覆盖了一种方法。如果你在同一个项目中,那么编译器会发出一个警告(或者一个错误?我不记得了),但是如果你从一个库中覆盖一个方法,那么......你运气不好......