3

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

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

一些对象.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end

一些对象.m

#import "SomeObject.h"

@implementation SomeObject

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

@end

someObject+Cat.h

#import <Foundation/Foundation.h>

#import "SomeObject.h"

@interface SomeObject (SomeObject)

- (void)doSomething;

@end

someObject+Cat.m

#import "SomeObject+Cat.h"

@implementation SomeObject (SomeObject)

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

@end

一些ObjectUser.h

#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end

一些ObjectUser.m

#import "SomeObjectUser.h"

#import "SomeObject.h"

@implementation SomeObjectUser

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

@end

测试.m

- (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!
4

2 回答 2

5

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

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

来自Objective-C 编程指南

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

(强调我的。)

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

于 2013-02-28T16:58:40.393 回答
0

更新

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


是的,根据this SO answer,(我会在找到它时发布官方Apple链接)。

一些警告,原始方法将无法访问,但您始终可以通过 to super,不能保证在另一个类别(在同一类上)声明的方法将被覆盖。

于 2013-02-28T16:57:35.253 回答