【问题标题】:Category on NSObject also works on ClassNSObject 上的类别也适用于 Class
【发布时间】:2015-07-01 20:34:05
【问题描述】:

所以我在 NSObject 上有一个名为 CustomCategory 的类别,如下所示:

#import <Foundation/Foundation.h>

@interface NSObject (CustomCategory)

-(BOOL)doSomething;

@end

#import "NSObject+CustomCategory.h"

@implementation NSObject (CustomCategory)

-(BOOL)doSomething
{
    NSLog(@"Done");
    return NO;
}

@end

理想情况下,这将适用于这样的对象:

NSObject* object = [NSObject new];
[object doSomething];

但是,我发现它也可以这样工作,没有问题:

[NSObject doSomething];

所以我想知道,既然它是我通过类别添加的实例方法,为什么它也适用于类?

【问题讨论】:

  • 显示Category的声明和定义代码。
  • 工作意味着它可以编译或运行 doSomething 中的代码
  • 所有的类也是 NSObjects(除了可能的 NSProxy)。
  • @user3125367差不多了。所有根类都是它们自己的类。所以从 NSObject 继承的每个类都是 NSObject,从 NSProxy 继承的每个类都是 NSProxy。
  • @zaph NSObject 并不特殊,它的处理方式与任何其他根类一样。

标签: objective-c


【解决方案1】:

NSObject 上的实例方法也是 NSObject 上的类方法。

这是因为 Objective-C 执行动态调度的方式。如果您向任何对象发送消息,则会在对象类中查找方法实现。如果您向类发送消息,那么您正在向类对象发送常规消息。在所谓的元类中查找实现。元类由编译器自动生成。类方法只是元类的实例方法。这由编译器透明地处理。

继承也适用于元类级别。因此,一个类的元类继承自其超类的元类。我们在那里有两个并行的继承层次结构。只有像 NSObject 这样的根类的处理方式不同。那里的元类不能从超类的元类继承,因为没有超类。对于根类,元类继承自根类本身。

由于类的类方法是其元类的实例方法,而 NSObject 元类继承自 NSObject 本身,NSObject 上的实例方法也是 NSObject 上的类方法。

【讨论】:

  • s/NSObject/根类/g。还有其他的根类,比如NSAtom、NSProxy等。
  • NSObject 的元类不是 NSObject。它绝对是分开的。
  • 是的,解决了这个问题。它不是 NSObject,它继承自 NSObject。否则根类根本就没有类方法。
  • @RichardJ.RossIII 是的,你是对的。但是 NSObject 的元类继承自 NSObject。修复了这个。
【解决方案2】:

供任何人在运行时源中寻找 this 的实际位置的参考,它当前位于 objc-runtime-new.mmmethodizeClass 函数中:

... snip...

// Root classes get bonus method implementations if they don't have 
// them already. These apply before category replacements.

if (cls->isRootMetaclass()) {
    // root metaclass
    addMethod(cls, SEL_initialize, (IMP)&objc_noop_imp, "", NO);
}

... snip ...

...并且元类的+initialize 方法将添加其实例中的所有方法实现并将它们转换为类方法。

而且,与@Sven 所说的相反,NSObject 的元类实际上并不是 NSObject。一个类在运行时总是有一个单独的元类,不管它是否是根。

【讨论】:

  • 你的 sn-p 什么也没说,它显示了根元类的 +initialize 来自哪里。我承认,我有点不准确,我只是检查了一下。 NSObject 的元类不是 NSObject,它直接继承自 NSObject。每个对象都有一个类,每个类都必须有一个超类,并且并行继承层次结构结合在一起。
【解决方案3】:

Objective C 中的每个Class 在内部都是一个对象,这意味着它是NSObject 的子类。

【讨论】:

  • 不完全。元类并不都继承自NSObject,也不是NSObject 的实例。它们实际上在方法解析期间被完全分开处理以处理根对象情况。
  • 没错,每个类都是一个对象。但是类对象类不会自动成为NSObject。 @RichardJ.RossIII:任何继承自 NSObject 的类的元类也继承自 NSObject。根类是它们自己的元类。
  • @Sven 但它不是NSObject 的实例,这使得这个答案具有误导性。真正的答案是,为了遗留目的,方法解析是为根类单独处理的。
  • @RichardJ.RossIII 唯一的区别是根类是它们自己的元类。对于每个继承自 NSObject 的类,它的元类也继承自 NSObject。
猜你喜欢
  • 1970-01-01
  • 2021-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-17
相关资源
最近更新 更多