Objective-C 是一种鸭式语言。这意味着有几件事你可以做或不能做,其中一件你不能做的是静态地获取对变量类型的引用。
具体来说,在你的表达中:
[_myArray.class new]
首先,_myArray.class被评估,然后将结果发送到new消息中。既然_myArray是nil开始,也会_myArray.class返回nil,并且new消息也会返回nil,因为发送任何消息nil都会返回nil(或返回类型具有的最接近零的表示形式)。这就是为什么它不起作用。
我怀疑你来自像 C# 这样的强类型语言;你现在所做的相当于Foo foo = (Foo)Activator.CreateInstance(foo.GetType()),这肯定会失败,因为foo.GetType()它不会编译或抛出异常(取决于它是类字段还是局部变量),因为它从未被赋值。在 Objective-C 中,它可以编译但不起作用。您想要的是Activator.CreateInstance(typeof(Foo)).,但请注意,Foo这里现在也已硬编码,因此您不妨创建一个new Foo().
您说编译器“知道对象的类型”。这并不完全正确。首先,NSArray和NSMutableArray是NSArray类簇的根类。这意味着两者都是抽象的,[NSArray alloc]并且[NSMutableArray alloc]返回一个子类的实例(NSCFArray上次我检查过,可能还有别的东西;我记得看过_NSArrayM)。也许[NSArray new]有效,但它并没有给你一个简单的NSArray.
其次,没有强制执行类型安全。考虑这段代码:
id foo = @"foo";
NSArray* bar = foo; // no warning!
因此,即使编译器认为这bar是 a NSArray,它实际上是 a NSString。如果我们插入您的代码:
id foo = @"foo";
NSArray* bar = foo; // no warning!
NSArray* baz = [bar.class new];
baz现在NSString也是。由于您要求 的运行时类bar,因此编译器与操作无关。
正是由于这种行为,您可能应该使用您知道的类来实例化您的对象,[NSArray new]而不是相信_myArray它是非nil的,并且是您认为的那样。