2013-07-04 4 views
6

Рассмотрим:Идентификаторы классов и компилятора ObjC?

@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

в последнем 'я» "представляет собой" Foo, который является классом. Итак, что такое класс класса?

  • classOf5 и classOf6

Ясно "Foo" и "Я" играть ту же самую роль в этом контексте. Как они это делают в

  • classOf3 и classOf4

Мне кажется, что «Foo» немного магии кролика.

Вы можете

@class Foo ; 

В некотором смысле, что

@class self ; 

не имеет смысла.

В конвейере генератора lexer для выполнения я могу понять, когда поток бит изменяется от связки символов до identifier к семантическому элементу, зависящему от языка. Но мне сложно определить точный характер идентификаторов класса ObjC.

Кто-нибудь?

(Это SO Question кажется несвязанный)

+0

Я предполагаю, что в ObjC классы Арен 't действительно объекты (и, следовательно, не имеют собственного метакласса), так что вполне возможно, что вызов класса '' 'класса' просто возвращает тот же объект намеренно. – millimoose

+1

Классы _are_ objects, @millimoose, но вторая половина вашего предложения - ответ. –

+0

@JoshCaswell Право. Я был смущен классом, который не документируется как таковой, а как структура. – millimoose

ответ

8

Вы можете увидеть ответ в 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().

+0

Я принимаю этот ответ за полезную ссылку, которую он предоставляет, но вопрос о природе «Foo» как идентификатора класса по-прежнему не отвечает. – verec

+0

Извините, я догадываюсь, что пропустил эту часть, но я не совсем уверен, что вы хотите знать. 'Foo' - это просто имя типа. Единственный раз, когда вы можете использовать литеральное имя класса для обращения к объекту класса, является то, что это приемник сообщения.Вероятно, это одна из причин, по которой '+ class' возвращает' self': в случае, если вам нужен объект класса в качестве аргумента для чего-то, но у вас нет экземпляра, вы можете сказать '[садовник plantLotsOf: [Oregano class]]; ' –

5
+ (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 wi го self


Разница между использованием Foo и self в методе класса является то, что, когда этот метод вызывается на подклассе self будет заменен на подкласс. например

@interface Bar : Foo 
@end 

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

Если вы действительно хотите получить класс класса (т.е. метаклассом), вам нужно использовать функцию ObjC выполнения от <objc/runtime.h>

id metaClass = objc_getMetaClass("Foo"); 
Смежные вопросы