2013-02-28 34 views
3

我知道使用类别覆盖方法是一种令人沮丧的做法。尽管如此,我必须处理一些这样做的代码。当我运行下面的代码时,我最初感到惊讶的是,在两种情况下都调用了类别方法,但考虑链接器必须在链接时如何为任何给定符号做出决定,这让我感觉更好。在类别中重写的方法是否总是优先于原始实现?

我的问题:假设除了我创建的其他类别不在其他类别中,我保证在我的类别中的实现始终是被调用的逻辑,只要它的标头从某处导入?

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! 
+0

@NikolaiRuhe我不同意,这些问题是根本不同的。 – 2013-02-28 16:58:42

+0

@MikeD问题有点不同,但答案对于这两个问题都是有效的。 – Sulthan 2013-02-28 17:00:58

+0

我确实已经先读过这个问题,现在可以看到那里有答案,但是指南说未定义的行为“不太可能是一个问题”,这让我想知道这里是否有更多的见解。 。 – 2013-02-28 17:28:50

回答

5

假定没有其他类别是不是我创造的那些其他的戏, 我保证,在我的类实现将永远是 因为它是从 进口也就是说只要称为标头中的逻辑某处?

无论您是否导入类别标题,我都怀疑这一点。头文件是编译器的信息;类在运行时添加到类中,并且在给定方法中使用哪个实现的选择在运行时发生。更重要的是...

Objective-C Programming Guide

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

(重点煤矿。)

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

+0

奇怪!除非我是疯了,否则这是对旧行为的一次突破性改变,即那些类别总是超过了非类别方法,但是没有办法使一个类别优先于另一个类别。接得好。 – Chuck 2013-02-28 19:52:13

+0

嘿,@Chuck。我不认为有什么变化 - 因为类的方法必须在类创建后添加到类中,我完全期望类的实现总是被使用。但OP要求提供*保证*,显然是一个很强的术语,并且文档说* undefined *,所以... – Caleb 2013-02-28 20:06:39

+0

同样来自文档:“您试图覆盖的框架定义的方法本身可能已经在类别,所以哪些实现优先没有被定义。“如果它没有在每一种情况下都被定义出来,他们为什么不愿意这样说呢?我质疑此文档... – 2013-02-28 20:06:53

0

UPDATE

在这样,请回答下面链接,指向的Objective-C类文档的链接已经死了。 Here is more up to date version。有一个关于避免名称冲突的部分。


是,根据本SO answer,(我将发布苹果官方的链接,当我找到它)。

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

相关问题