I have the following code:
id anArray = [NSArray arrayWithObjects:@1, @2, nil];
NSLog(@"anArrayClass - %@", [anArray class]);
NSLog(@"NSArrayClass - %@", [NSArray class]);
And I expect both output are NSArray
, however the output turns out to be:
2016-08-18 21:08:53.628 TestUse[9279:939745] anArrayClass - __NSArrayI
2016-08-18 21:08:53.629 TestUse[9279:939745] NSArrayClass - NSArray
Then I create a test class called CAJTestClass
and create an instance of that class:
id testInstance = [CAJTestClass new];
NSLog(@"testInstanceClass - %@", [testInstance class]);
NSLog(@"cajTestClass - %@", [CAJTestClass class]);
This time the output becomes:
2016-08-18 21:08:53.629 TestUse[9279:939745] testInstanceClass - CAJTestClass
2016-08-18 21:08:53.629 TestUse[9279:939745] cajTestClass - CAJTestClass
This time the result is what I expected. But why would [anArray class]
to be a __NSArrayI
?
An explanation from "Effective Objective-C" is that NSArray
is a part of a "class cluster"(which I think is a series of classes that have inheriting relationships). But CAJTestClass
is also a subclass of NSObject
. Am I wrong?
EDIT: Thanks for all your answers. But my question is exactly why I get different result in this two cases if it should contribute to the affairs of "class cluster"?
EDIT: Thanks for all your answers. But my question is exactly why I get different result in this two cases if it should contribute to the affairs of "class cluster"?
Because the test code is completely different. You're calling an NSArray
method that returns a subclass of NSArray
, but you're calling [CAJTestClass new]
, which returns CAJTestClass
itself. If you make them be the same, then you get the same results:
@interface CAJTestClass : NSObject
+ (instancetype)testClassWithMagic;
@end
@interface __MagicTestSubclass : CAJTestClass
@end
@implementation CAJTestClass
+ (instancetype)testClassWithMagic {
return [__MagicTestSubclass new];
}
@end
@implementation __MagicTestSubclass
@end
Now using your test code:
id testInstance = [CAJTestClass testClassWithMagic];
NSLog(@"testInstanceClass - %@", [testInstance class]);
NSLog(@"cajTestClass - %@", [CAJTestClass class]);
2016-08-18 09:57:15.126 test[72004:47882338] testInstanceClass - __MagicTestSubclass
2016-08-18 09:57:15.127 test[72004:47882338] cajTestClass - CAJTestClass
rmaddy raises the possibility that you have a different question and he may be correct, so I'll answer that one as well.
[anArray class]
is the result of passing the -class
message to the instance anArray
. The usual thing for an instance to do when it receives the -class
message is to return the specific class it was initialized as (its specific subclass). This is not universal (KVO classes intentionally break this rule and it's even possible to change classes at runtime), but it is the common approach. This is the isa
pointer in the struct that tells the dispatcher which set of methods to use. So you get the actual as-instantiated class object (__NSArrayI
).
[NSArray class]
is the result of passing the +class
message to the class object NSArray
. The usual thing for a class object to is return self
(I don't know any classes that violate that rule; it may not be legal to violate that rule). So you get the class you passed the message to (NSArray
).