在Objective C,为什么我允许指定一个NSArray到一个NSMutableArray没有错

2019-07-21 02:13发布

我由怪异的行为,通过下面的例子说明不安:

NSMutableArray *a1 = [[NSMutableArray alloc] init]; // fine
NSMutableArray *a2 = [NSMutableArray array];        // fine, too

// compiler reports incompatible pointer types; good:
NSMutableArray *a3 = [[NSArray alloc] init]; 

// compiler says nothing and is happy to assign this!
NSMutableArray *a4 = [NSArray array]; 

initarray两者的方法NSArrayNSMutableArray类返回id 。 然而,当我把这些方法的行为是根本不一样的,和铛让我快乐地分配一个空NSArrayNSMutableArray变量!

事实证明, 铛会自动更改的一些方法,包括返回类型init家庭, instancetype ,从而能够确定在那个编译时[[NSArray alloc] init]返回NSArray * ,而不是一个NSMutableArray * 。 但这种检查根本不与工作array方法。

为什么? 如果不喜欢我的最后一个例子线产生至少一个警告? 不是所有的这些方法为什么声明为返回instancetype ? 它会在将来改变?


更新

好消息:作为的iOS 7, [NSArray array]返回instancetype ,所以分配到a4上述的组合也产生一个警告。 像其他方法arrayWithContentsOfFile:arrayWithContentsOfURL还是回到id ,但...

Answer 1:

但这种检查根本不与阵列方法工作。 为什么?

正如你所链接的文档介绍,这是因为-array不会产生一个公认的相关结果类型 。 ObjC是非常动态的-编译器不能保证的结果类型+array 。 它确实让一些方法是假设,因为命名约定是明确的(如+alloc-init+new-self等)。 因此,这只是实现诉诸命名约定。

编译器也验证了你可能不希望地区的一些命名约定:

@implementation NSArray (DEMO)

- (id)initStr
{
    return [NSString new]; // << warning. RE: init prefix
}

@end

如果不喜欢我的最后一个例子线产生至少一个警告? 不是所有的这些方法为什么声明为返回instancetype? 它会在将来改变?

instancetype引入大约一年前(从它的外观)。 某些API是几十年前写的。 我怀疑这会发生- 在时间 -因为(如果正确使用),它可以指出很多在现有代码的问题。 当然,这些变化会打破现有的构建(再次,通常是很好的修正,如果在正确的地方声明)。

因此,提交bug,并给予工具和库几年来更新。 假设进行更改时,它可能会发生在一个主要的操作系统更新。

或许,这将是最好的,如果它被作为一段时间的可选警告开启(系统头的情况下)。 当然,他们仍然可以与新的API老的编译器向后兼容采用它。

此外,这种变化可以很容易地(不是早期编译器将使之间的语义差别感改装idinstancetype通过简单的typedef)。 有一个typedef的一个问题是,它是一个全球性的声明 - 编译器可能会限制一个字/修改/属性给定的范围内,而不会导致通过增加全球的typedef模拟关键字的所有痛苦。 苹果的GCC可能永远不会支持instancetype ,所以合乎逻辑的方式来介绍它为苹果的GCC可能是一个全球性typedefid ,这可能导致一些人的问题(无语义的好处,如果这条路拍摄)。 另外,对与重大的变动在过去已经取得苹果。



Answer 2:

事实证明,你不只是不允许使用错误数组类型,你被允许使用错误类型的任何物体与便利初始化返回id 。 例如,该编译没有任何一个警告:

NSMutableArray *a4 = [NSDictionary dictionary]; 

这是使用的副作用id退出类型安全的,正如你注意,它应该被弃用的行为,并与instancetype取代(的方式使用以上时就抛出一个不兼容的类型警告)。

不幸的是,这不是一个错误。 instancetype是一个相当新的关键字,它的采用并不普遍的是,这将是一个大胆的举动,开始使用它整个苹果公司的框架。 你永远不知道,总有希望在接下来的SDK!



文章来源: In Objective C, why am I allowed to assign an NSArray to an NSMutableArray without error or warning?