【问题标题】:ObjC Class identifiers & compiler magic?ObjC 类标识符和编译器魔法?
【发布时间】:2013-07-04 02:46:38
【问题描述】:

考虑:

@interface Foo : NSObject

+ (void) dump ;

@end

@implementation Foo

+ (Class) classOf1 {
    return self ;
}

+ (Class) classOf2 {
    return [Foo class] ;
}

+ (Class) classOf3 {
    return [[[Foo class] new] class] ;
}

+ (Class) classOf4 {
    return [[self new] class] ;
}

+ (Class) classOf5 {
    return [[[self alloc] init] class] ;
}

+ (Class) classOf6 {
    return [[[Foo alloc] init] class] ;
}

+ (Class) classOf7 {
    return [self class] ;
}

+ (void) dump {
    NSLog(@"classOf1 %@<0x%08.8lx>", [self classOf1], (unsigned long)[[self classOf1] hash]) ;
    NSLog(@"classOf2 %@<0x%08.8lx>", [self classOf2], (unsigned long)[[self classOf2] hash]) ;
    NSLog(@"classOf3 %@<0x%08.8lx>", [self classOf3], (unsigned long)[[self classOf3] hash]) ;
    NSLog(@"classOf4 %@<0x%08.8lx>", [self classOf4], (unsigned long)[[self classOf4] hash]) ;
    NSLog(@"classOf5 %@<0x%08.8lx>", [self classOf5], (unsigned long)[[self classOf5] hash]) ;
    NSLog(@"classOf6 %@<0x%08.8lx>", [self classOf6], (unsigned long)[[self classOf6] hash]) ;
    NSLog(@"classOf7 %@<0x%08.8lx>", [self classOf7], (unsigned long)[[self classOf7] hash]) ;
}

@end

还有输出:

    2013-07-04 03:20:20.404 WC[29862:c07] classOf1 Foo<0x0002a2e4>
    2013-07-04 03:20:21.075 WC[29862:c07] classOf2 Foo<0x0002a2e4>
    2013-07-04 03:20:21.628 WC[29862:c07] classOf3 Foo<0x0002a2e4>
    2013-07-04 03:20:22.229 WC[29862:c07] classOf4 Foo<0x0002a2e4>
    2013-07-04 03:20:22.805 WC[29862:c07] classOf5 Foo<0x0002a2e4>
    2013-07-04 03:20:23.387 WC[29862:c07] classOf6 Foo<0x0002a2e4>
    2013-07-04 03:20:25.235 WC[29862:c07] classOf7 Foo<0x0002a2e4>

所有 7 个案例都返回完全相同的值!

对我来说最令人费解的案例:

  • classOf1 和 classOf7

在后者中,“self”“代表”Foo,它是一个类。那么什么是类的类呢?

  • classOf5 和 classOf6

显然,“Foo”和“self”在这种情况下扮演着完全相同的角色。就像他们在

  • classOf3 和 classOf4

在我看来,“Foo”有点像魔法兔子。

你可以

@class Foo ;

以某种方式

@class self ;

没有意义。

在词法分析器到运行时生成器的管道中,我可以理解比特流何时从一堆字符变为 identifier 再到依赖于语言的语义元素。但是我很难弄清楚 ObjC 类标识符的确切性质。

有人吗?

(这个SO Question 似乎无关)

【问题讨论】:

  • 我猜在 ObjC 中,类并不是真正的对象(因此没有自己的元类),因此完全有可能在 Class 上调用 class只是故意返回同一个对象。
  • 对象,@millimoose,但你句子的后半部分就是答案。
  • @JoshCaswell 对。我对Class 没有被记录为这样,而是作为一个结构而感到困惑。

标签: objective-c


【解决方案1】:

你可以在NSObject's implementation看到答案:

+ (Class)class {
    return self;
}

- (Class)class {
    return object_getClass(self);
}

向类对象发送class 不会返回它的元类,只返回类对象本身。

如果出于某种原因想要元类对象,则必须使用运行时函数object_getClass(),如下所示:

NSLog(@"%d", class_isMetaClass(object_getClass([NSString class])));
// Prints 1

您还可以使用objc_getMetaClass() 获取类名称 的元类。

【讨论】:

  • 我接受这个答案是因为它提供了有用的链接,但关于“Foo”作为类标识符的性质的问题仍未得到解答。
  • 对不起,我想我错过了那部分,但我不太确定你想知道什么。 Foo 只是一个类型名称。只有当它是消息的接收者时,才能使用文字类名来引用类对象。事实上,这可能是+class 返回self 的原因之一:如果您需要类对象作为某事物的参数但手边没有实例,您可以说[gardener plantLotsOf:[Oregano class]];
【解决方案2】:
+ (Class) classOf1 {
    return self ;
}

类方法中的self是当前类的Class对象,所以这里self是类Foo的类对象


+ (Class) classOf2 {
    return [Foo class] ;
}

这是Foo类的类对象


+ (Class) classOf3 {
    return [[[Foo class] new] class] ;
}

这是一样的

Class fooClass = [Foo class];
id fooInstance = [fooClass new];
return [fooInstance class];

再一次,给你Foo类的类对象


+ (Class) classOf4 {
    return [[self new] class] ;
}

与上一个相同,只需将[Foo class] 替换为self


+ (Class) classOf5 {
    return [[[self alloc] init] class] ;
}

和上一个一样,只是把[Foo new]换成[[Foo alloc] init]


+ (Class) classOf6 {
    return [[[Foo alloc] init] class] ;
}

与上一个相同,只需将self 替换为Foo


+ (Class) classOf7 {
    return [self class] ;
}

与第二个相同,只需将Foo 替换为self


在类方法中使用Fooself 的区别在于,当在子类上调用此方法时,self 将被替换为子类。例如

@interface Bar : Foo
@end

Class barClass = [Bar classOf1]; // same as [Bar class]
Class fooClass = [Bar classOf2]; // same as [Foo class]

如果你真的想获取类的类(即元类),你需要使用来自&lt;objc/runtime.h&gt;的objc运行时函数

id metaClass = objc_getMetaClass("Foo");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-12
    • 2022-01-27
    • 1970-01-01
    • 2020-11-13
    • 2017-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多