我由怪异的行为,通过下面的例子说明不安:
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];
既init
和array
两者的方法NSArray
和NSMutableArray
类返回id
。 然而,当我把这些方法的行为是根本不一样的,和铛让我快乐地分配一个空NSArray
到NSMutableArray
变量!
事实证明, 铛会自动更改的一些方法,包括返回类型init
家庭, instancetype
,从而能够确定在那个编译时[[NSArray alloc] init]
返回NSArray *
,而不是一个NSMutableArray *
。 但这种检查根本不与工作array
方法。
为什么? 如果不喜欢我的最后一个例子线产生至少一个警告? 不是所有的这些方法为什么声明为返回instancetype
? 它会在将来改变?
更新
好消息:作为的iOS 7, [NSArray array]
返回instancetype
,所以分配到a4
上述的组合也产生一个警告。 像其他方法arrayWithContentsOfFile:
或arrayWithContentsOfURL
还是回到id
,但...
但这种检查根本不与阵列方法工作。 为什么?
正如你所链接的文档介绍,这是因为-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老的编译器向后兼容采用它。
此外,这种变化可以很容易地(不是早期编译器将使之间的语义差别感改装id
和instancetype
通过简单的typedef)。 有一个typedef的一个问题是,它是一个全球性的声明 - 编译器可能会限制一个字/修改/属性给定的范围内,而不会导致通过增加全球的typedef模拟关键字的所有痛苦。 苹果的GCC可能永远不会支持instancetype
,所以合乎逻辑的方式来介绍它为苹果的GCC可能是一个全球性typedef
的id
,这可能导致一些人的问题(无语义的好处,如果这条路拍摄)。 另外,对与重大的变动在过去已经取得苹果。
事实证明,你不只是不允许使用错误数组类型,你被允许使用错误类型的任何物体与便利初始化返回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?