如果两个ObjC类别覆盖相同的方法会发生什么?

时间:2010-07-11 05:28:49

标签: objective-c cocoa inheritance methods categories

我知道有关Objective-C类别的一些规则:

  
      
  1. 类别方法不应覆盖现有方法(类或实例)
  2.   
  3. 为同一个类实现相同方法的两个不同的类别将导致未定义的行为
  4.   

我想知道当我覆盖同一类别中我自己的一个类别方法时会发生什么。例如:

@interface NSView (MyExtensions)
- (void)foo; // NSView category implementation
@end

@interface MyClass : NSView
{ }
@end

@interface MyClass (MyExtensions)
- (void)foo; // MyClass category implementation
@end

定义了这些接口后,运行以下代码时将执行哪种方法?

MyClass * instance = [[MyClass alloc] initWith...];
[instance foo];
[instance release];

注意:使用我的编译器,MyClass实现优先,但我不确定是否可以保证发生,或者只是一种特定的未定义行为。

2 个答案:

答案 0 :(得分:32)

延伸到绘制的答案:

这是层次结构的问题。类别实际上只是组织源文件的一种方式。编译时,类的所有方法(包括在任何类别中定义的方法)最终都在同一个文件中。

您可以在常规类界面中执行任何操作,您可以在类别中执行任何操作,而不应该在常规类界面中执行的任何操作都不应该在类别中执行。

所以:

  

不应覆盖类别方法   现有方法(类或实例)

您可以使用常规类接口中定义的方法来覆盖继承的方法,以便您可以覆盖类别中的继承方法。

但是,您永远不会尝试在同一普通接口中使用两个相同的方法定义,因此您不应该在类别中具有与普通接口中的方法同名的方法或同一类别中的方法类。由于所有方法定义最终都在同一个编译文件中,因此它们显然会发生冲突。

  

实施两个不同的类别   相同的方法导致undefined   行为

这应该改写为“为同一个类 实现相同方法 的两个不同类别会导致未定义的行为。”同样,因为任何一个类的所有方法最终都在同一个文件中,所以在同一个类中有两个方法显然会引起奇怪。

您可以使用类别来提供覆盖超类方法的方法,因为类及其超类是两个不同的类。

如果您对某个类别是否会导致问题感到困惑,请问问自己:“如果我将这些方法复制并粘贴到类'.h / .m文件中,那么该类别中的方法是否有效?”如果答案是“是”那么你就明白了。如果“不”,那么你就遇到了问题。

答案 1 :(得分:12)

每个类的每个方法都有一个实现。类别为特定类添加或替换方法。这意味着您正在看到的行为,其中MyClass有一个foo而NSView有另一个foo,这个行为定义得很好。 MyClass的任何实例都将具有与不是MyClass的任何NSView实例不同的foo,就像在主实现中定义了foo而不是类别一样。您甚至可以从MyClass调用[super foo]来访问为NSView定义的foo