Objective c 类别中重写的方法是否总是优先于原始实现?

Objective c 类别中重写的方法是否总是优先于原始实现?,objective-c,methods,overriding,objective-c-category,Objective C,Methods,Overriding,Objective C Category,我理解通过使用类别重写方法是一种不鼓励的做法。尽管如此,我必须处理一些代码来实现这一点。当我运行下面的代码时,我最初对我的category方法在这两种情况下都被调用感到惊讶,尽管考虑到链接器必须在链接时如何对任何给定的符号做出决定让我感觉更好 我的问题:假设除了我创建的类别之外,没有其他类别在发挥作用,我是否可以保证我的类别中的实现将始终是调用的逻辑,只要它的头是从某处导入的 someObject.h #import <Foundation/Foundation.h> @inter

我理解通过使用类别重写方法是一种不鼓励的做法。尽管如此,我必须处理一些代码来实现这一点。当我运行下面的代码时,我最初对我的category方法在这两种情况下都被调用感到惊讶,尽管考虑到链接器必须在链接时如何对任何给定的符号做出决定让我感觉更好

我的问题:假设除了我创建的类别之外,没有其他类别在发挥作用,我是否可以保证我的类别中的实现将始终是调用的逻辑,只要它的头是从某处导入的

someObject.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end
someObject+Cat.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end
someObjectUser.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end
#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end
测试.m

#import "SomeObject.h"

@implementation SomeObject

- (void)doSomething
{
    NSLog(@"Original");
}

@end
#import "SomeObject+Cat.h"

@implementation SomeObject (SomeObject)

- (void)doSomething
{
    NSLog(@"New!");
}

@end
#import "SomeObjectUser.h"

#import "SomeObject.h"

@implementation SomeObjectUser

- (void)useSomeObject
{
    [[SomeObject new] doSomething];
}

@end
- (void)testExample
{
    [[SomeObject new] doSomething];
    [[SomeObjectUser new] useSomeObject];
}
结果

2013-02-28 11:32:37.417 CategoryExample[933:907] New!
2013-02-28 11:32:37.419 CategoryExample[933:907] New!

更新

在下面链接的SO答案中,指向Objective-C类别文档的链接已失效。有一节是关于避免名称冲突的


是的,根据这个,(我会在找到苹果官方链接后发布)

在一些警告中,原始方法将不可访问,但您始终可以转到
super
,不能保证在另一个类别(在同一个类上)中声明的方法将被重写

假设除了我创建的类别之外,没有其他类别在发挥作用, 我是否保证我的类别中的实现将始终 只要从导入其标头,就调用该逻辑 在什么地方

我怀疑是否导入类别标题是否重要。标题是编译器的信息;类别在运行时添加到类中,并且在运行时选择用于给定方法的实现。更重要的是

发件人:

如果类别中声明的方法的名称与方法相同 在原始类中,或在同一目录上的另一个类别中的方法中 类(甚至是超类),行为未定义 方法实现在运行时使用。这不太可能是一个问题 如果您在自己的类中使用类别,但可能导致 使用类别将方法添加到标准Cocoa或 可可触摸课程

(我的重点。)


考虑到单词undefined的使用,我想说问题的答案是否定的,当您在一个类别中重新实现一个现有方法时,不能保证将使用哪个实现。实际上,如果该类是您自己的,那么您的类别的方法很可能会被选择,并且我相信,如果它在测试给定版本的编译器和运行时时时起作用,那么它是可靠的。

@NikolaiRuhe我不同意,问题根本不同。@MikeD问题有点不同,但答案对这两个问题都有效。我确实先读了那个问题,现在可以看到其中有一个答案,但是事实上,指南说未定义的行为“不太可能是问题”让我想知道这里是否还有其他的见解…奇怪!除非我疯了,否则这是一个突破性的改变,与旧行为不同,旧行为是类别总是优先于非类别方法,但没有办法使一个类别优先于另一个类别。接得好。嘿,恰克。我认为没有什么真正的改变——因为在创建类之后,必须将category方法添加到类中,所以我完全希望始终使用category实现。但是OP要求提供一个保证,显然是一个强有力的术语,文档中说未定义,因此……也来自文档:“您试图覆盖的框架定义的方法本身可能已经在一个类别中实现,因此没有定义哪个实现优先。”如果不是在每种情况下都定义它,他们为什么要特意这么说?我对这方面的文档提出质疑……还说:“例如,如果您在NSObject上的某个类别中重写windowWillClose:delegate方法,则程序中的所有窗口代理都会使用category方法进行响应。”。听起来好像已经定义好了,类别赢了。@BenFlynn问题是你不知道类别添加到类中的顺序。因此,如果作为类接口一部分的方法实际上是在一个类别的框架内实现的,那么您不知道是否会先加载类别,然后让框架的类别覆盖您的方法,反之亦然。在您自己的类的实践中,是的,您的类别实现将覆盖您的类中的实现,但未定义意味着您不应该依赖于该行为,它可能会改变,即使现在也可能不总是有效。