In Objective-C, you can invoke class methods with:
[MyClass aClassMethod];
And you can query an instance’s kind with:
[someInstance isKindOfClass:[MyClass class]];
But, why do we need to do [MyClass class], and not simply provide MyClass like this:
[someInstance isKindOfClass:MyClass];
Is there a reason that the compiler is fine with encountering MyClass as a receiver (a pointer type) but not as an argument? Is it a limitation of parsing the language? Or perhaps a limitation of the compiler?
Ooooh… fun question. The answer is a c-ism.
Consider:
Now, say you have:
In that context, the compiler sees
MyClassas a type definition. The*says that the variablemis apointer to a hunk o' memory that contains one (or many -- don't forget your C pointer-fu) MyClass instances.In other words,
MyClassis a type.But, in the context of something like:
xmust be an rvalue or, in human terms, the value of an expression. A type, however, cannot be used as an rvalue.That
[MyClass class]works is actually a bit of a hack, both in the language and the compiler in that the grammar specifically allows a type name to be the message receiver (to be the target of a method call).And, as a matter of fact, you can do:
It’ll all work. However, you can’t do the following but the error message is illuminating:
error: ‘NSUInteger’ is not an Objective-C class name or alias
Now, why not special case it everywhere as a bare name?
That colludes type names and rvalues and you quickly end up having to swallow something like
[foo isKindOfClass: (MyClass)];while barfing on[foo isKindOfClass: (MyClass *)];which then encroaches upon typecasting territory in a rather uncomfortable fashion.