在类别中重写的方法是否始终优先于原始实现?

Ben*_*ynn 3 methods overriding objective-c objective-c-category

我知道通过使用类别来覆盖方法是一种沮丧的做法.尽管如此,我还是要处理一些执行此操作的代码.当我运行以下代码时,我最初感到惊讶的是,在两种情况下都调用了我的类别方法,尽管考虑链接器必须如何在链接时为任何给定符号做出决定让我感觉更好.

我的问题:假设除了我创建的类别之外没有其他类别可用,我保证我的类别中的实现将始终是被调用的逻辑,只要它的标题是从某个地方导入的吗?

someObject.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end
Run Code Online (Sandbox Code Playgroud)

someObject.m

#import "SomeObject.h"

@implementation SomeObject

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

@end
Run Code Online (Sandbox Code Playgroud)

someObject + Cat.h

#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end
Run Code Online (Sandbox Code Playgroud)

someObject + Cat.m

#import "SomeObject+Cat.h"

@implementation SomeObject (SomeObject)

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

@end
Run Code Online (Sandbox Code Playgroud)

someObjectUser.h

#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end
Run Code Online (Sandbox Code Playgroud)

someObjectUser.m

#import "SomeObjectUser.h"

#import "SomeObject.h"

@implementation SomeObjectUser

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

@end
Run Code Online (Sandbox Code Playgroud)

Test.m

- (void)testExample
{
    [[SomeObject new] doSomething];
    [[SomeObjectUser new] useSomeObject];
}
Run Code Online (Sandbox Code Playgroud)

结果

2013-02-28 11:32:37.417 CategoryExample[933:907] New!
2013-02-28 11:32:37.419 CategoryExample[933:907] New!
Run Code Online (Sandbox Code Playgroud)

Cal*_*leb 5

假设除了我创建的类别之外没有其他类别在进行,我保证我的类别中的实现将始终是被调用的逻辑,只要它的标题是从某处导入的吗?

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

来自Objective-C编程指南:

如果在类别中声明的方法的名称与原始类中的方法相同,或者在同一个类(或甚至是超类)上的另一个类别中的方法相同,关于在哪个方法实现中使用哪个方法实现的行为是未定义的.运行.如果您使用具有自己类的类别,则不太可能成为问题,但在使用类别向标准Cocoa或Cocoa Touch类添加方法时可能会导致问题.

(强调我的.)

鉴于使用了未定义的单词,我会说问题的答案是否定的,当您重新实现类别中的现有方法时,无法保证将使用哪种实现.实际上,如果类是您自己的,那么很可能会选择类别的方法,并且如果它在测试给定版本的编译器和运行时,我相信它是可靠的.