如果两个 ObjC 类别覆盖相同的方法会发生啥?
Posted
技术标签:
【中文标题】如果两个 ObjC 类别覆盖相同的方法会发生啥?【英文标题】:What happens if two ObjC categories override the same method?如果两个 ObjC 类别覆盖相同的方法会发生什么? 【发布时间】:2011-03-14 09:54:25 【问题描述】:我知道一些关于 Objective-C 类别的规则:
类别方法不应覆盖现有方法(类或实例) 两个不同的类对同一个类实现相同的方法会导致未定义的行为
我想知道当我在同一类别中覆盖我自己的类别方法之一时会发生什么。例如:
@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 实现优先,但我不确定这是否会发生,或者只是一种特定的未定义行为。
【问题讨论】:
【参考方案1】:继续向前回答:
这是等级制度的问题。类别实际上只是组织源文件的一种方式。编译时,一个类的所有方法,包括在任何类别中定义的方法,最终都在同一个文件中。
您可以在常规类界面中执行的任何操作都可以在类别中执行,以及您在常规类界面中不应该在类别中执行的任何操作。
所以:
类别方法不应覆盖 现有方法(类或实例)
您可以使用在常规类接口中定义的方法来覆盖继承方法,这样您就可以覆盖一个类别中的继承方法。
但是,您永远不会尝试在同一个普通接口中拥有两个相同的方法定义,因此您永远不应该在一个类别中拥有与普通接口或同一类别中的另一个类别中的方法同名的方法班级。由于所有方法定义最终都在同一个编译文件中,因此它们显然会发生冲突。
两个不同的类别实现 相同的方法导致未定义 行为
这应该重写为“两个不同的类别实现相同的方法同一个类会导致未定义的行为。”同样,因为任何一个类的所有方法最终都在同一个文件中,所以在同一个类中有两个方法显然会导致怪异。
您可以使用类别来提供覆盖超类方法的方法,因为一个类及其超类是两个不同的类。
如果您曾经对某个类别是否会引起问题感到困惑,请问自己:“如果我将类别中的方法全部复制并粘贴到类的 .h/.m 文件中,它们会起作用吗?”如果答案是“是”,那么你就很清楚了。如果“否”,那么你就有问题了。
【讨论】:
+1 谢谢。这是一个很好的描述方式。我还更改了规则 #2 的措辞以匹配您的。【参考方案2】:每个类的每个方法都有一个实现。类别添加或替换特定类的方法。这意味着您所看到的行为,其中 MyClass 有一个 foo
而 NSView 有另一个 foo
,是明确定义的。 MyClass 的任何实例都将具有与不是 MyClass 的任何 NSView 实例不同的foo
,就像foo
已在主实现中定义而不是类别一样。您甚至应该能够从 MyClass 调用 [super foo]
来访问为 NSView 定义的 foo
。
【讨论】:
在超类的Category中声明实现的Category方法中重写是否正确?以上是关于如果两个 ObjC 类别覆盖相同的方法会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章