Objective c 如果两个ObjC类别覆盖同一个方法,会发生什么情况?

Objective c 如果两个ObjC类别覆盖同一个方法,会发生什么情况?,objective-c,cocoa,inheritance,methods,categories,Objective C,Cocoa,Inheritance,Methods,Categories,我知道一些关于Objective-C类别的规则: 类别方法不应覆盖现有方法(类或实例) 为同一类实现相同方法的两个不同类别将导致未定义的行为 我想知道当我在同一个类别中重写我自己的一个类别方法时会发生什么。例如: @interface NSView (MyExtensions) - (void)foo; // NSView category implementation @end @interface MyClass : NSView { } @end @interface MyClass

我知道一些关于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实现优先,但我不确定这是否保证会发生,或者仅仅是一种特定的未定义行为。

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

    要扩展绘图时的回答:

    这是等级问题。类别实际上只是组织源文件的一种方法。编译时,一个类的所有方法,包括在任何类别中定义的方法,最终都位于同一个文件中

    在常规类接口中可以执行的任何操作都可以在类别中执行,而在常规类接口中不应该执行的任何操作都不应该在类别中执行

    因此:

    类别方法不应重写 现有方法(类或实例)

    您可以使用在常规类接口中定义的方法重写继承的方法,以便可以重写类别中的继承方法

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

    两个不同的类别 相同的方法会导致未定义 行为

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

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


    如果您曾经对某个类别是否会导致问题感到困惑,请扪心自问:“如果我将类别中的方法全部复制并粘贴到类.h/.m文件中,这些方法是否有效?”如果答案是“是”,那么您就清楚了。如果“否”,则表示您遇到了问题。

    +1谢谢。这是一个很好的描述方式。我还更改了规则#2上的措辞以匹配您的。重写在超类的类别中声明和实现的类别内方法是否正确?