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
的,并且是您认为的那样。