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

时间:2013-02-28 16:46:53

标签: objective-c methods override objective-c-category

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

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

someObject.h

#import <Foundation/Foundation.h>

@interface SomeObject : NSObject

- (void)doSomething;

@end

someObject.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

someObjectUser.h

#import <Foundation/Foundation.h>

@interface SomeObjectUser : NSObject

- (void)useSomeObject;

@end

someObjectUser.m

#import "SomeObjectUser.h"

#import "SomeObject.h"

@implementation SomeObjectUser

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

@end

Test.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!

2 个答案:

答案 0 :(得分:5)

  

假设除了我创建的其他类别之外没有其他类别,   我保证我的类别中的实施将永远是   只要从中导入标头,就会调用该逻辑   某处?

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

来自Objective-C Programming Guide

  

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

(强调我的。)

考虑到使用 undefined 这个词,我会说问题的答案是不,当你重新使用时,无法保证将使用哪种实现 - 实现类别中的现有方法。实际上,如果这个类是你自己的,那么很可能会选择你的类别的方法,并且如果它适用于测试给定版本的编译器和运行时,我相信它是可靠的。

答案 1 :(得分:0)

<强>更新

在下面链接的SO答案中,指向Objective-C类别文档的链接已经死亡。 Here is more up to date version。有一节关于避免姓名冲突。


是的,根据此SO answer,(我会在发现时发布官方Apple链接)。

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