Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在目标C中,为什么允许我在没有错误或警告的情况下将NSArray分配给NSMutableArray?_Objective C_Cocoa_Clang - Fatal编程技术网

Objective c 在目标C中,为什么允许我在没有错误或警告的情况下将NSArray分配给NSMutableArray?

Objective c 在目标C中,为什么允许我在没有错误或警告的情况下将NSArray分配给NSMutableArray?,objective-c,cocoa,clang,Objective C,Cocoa,Clang,我被一种奇怪的行为所困扰,如下例所示: NSMutableArray *a1 = [[NSMutableArray alloc] init]; // fine NSMutableArray *a2 = [NSMutableArray array]; // fine, too // compiler reports incompatible pointer types; good: NSMutableArray *a3 = [[NSArray alloc] init]; //

我被一种奇怪的行为所困扰,如下例所示:

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]; 
NSArray
NSMutableArray
类的
init
array
方法都返回
id
。然而,我调用这些方法时的行为完全不同,而clang让我很高兴地将一个空的
NSArray
分配给
NSMutableArray
变量

结果是,并因此能够在编译时确定
[[NSArray alloc]init]
返回
NSArray*
而不是
NSMutableArray*
。但是这个检查根本不适用于
array
方法

为什么??像我上一个例子那样的行不应该至少产生一个警告吗?为什么所有这些方法都不声明为返回
instancetype
?将来会改变吗


更新


好消息:从iOS 7开始,
[NSArray array]
返回
instancetype
,因此上面对
a4
的赋值也会产生警告。其他方法,如
arrayWithContentsOfFile:
arrayWithContentsOfURL
仍然返回
id
,尽管…

事实证明,您不仅可以使用错误的数组类型,还可以使用带有返回
id
的方便初始值设定项的任何对象的错误类型。例如,编译时不会出现警告:

NSMutableArray *a4 = [NSDictionary dictionary]; 
这是使用
id
选择退出类型安全性的一个副作用,正如您所注意到的,它应该是不推荐的行为,并替换为instancetype(以上述方式使用时会引发不兼容的类型警告)

不幸的是,这不是一个bug
instancetype
作为一个全新的关键词,它的应用还没有普及,在苹果的整个框架中开始使用它将是一个大胆的举动。你永远不会知道,下一个SDK总是有希望的

但是这个检查对于数组方法根本不起作用。为什么?

正如您链接的文档所描述的,这是因为
-array
不会生成可识别的相关结果类型。ObjC是非常动态的——编译器不能保证
+数组的结果类型。由于命名约定定义良好(例如,
+alloc
-init
+new
-self
,等等),因此在某些方法中确实做出了这种假设。因此,这个实现只是诉诸命名约定

编译器还会在您可能不期望的区域验证某些命名约定:

@implementation NSArray (DEMO)

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

@end
@实现NSArray(演示)
-(id)initStr
{

返回[NSString new];//我会在上提交一个bug,并在这里提到bug编号。@ericgorr问题是,它不是bug。@Jean Philippellet:很抱歉,我复制了你的问题…@AnoopVaidya我想你误解了
id
的用途。bug报告rdar://13357852Thanks. 我一直想知道为什么这些方法在第一个p中应该返回
id
lace而不是返回的实际类型。为什么要像这样丢弃类型安全性?这样它们就不会破坏子类。如果在初始值设定项中放弃类型安全性,那么子类S可以重写t的init方法并返回自己,而不带类型检查警告。如果ObjC像java一样,初始值设定项是唯一的,默认情况下不会继承,则不是问题。嗯,我发现不返回
id
实际上不是问题,因为clang允许您在重写的方法中返回协变子类型。所以子类也应该可以。