instancetype和id

一、什么是instancetype

instancetype是clang 3.5开始,clang提供的一个关键字,表示某个方法返回的未知类型的Objective-C对象。我们都知道未知类型的的对象可以用id关键字表示,那为什么还会再有一个instancetype呢?

二、关联返回类型(related result types)

根据Cocoa的命名规则,满足下述规则的方法:

1、类方法中,以alloc或new开头

2、实例方法中,以autorelease,init,retain或self开头

会返回一个方法所在类类型的对象,这些方法就被称为是关联返回类型的方法。换句话说,这些方法的返回结果以方法所在的类为类型,说的有点绕口,请看下面的例子:

@interface NSObject

+ (id)alloc;

- (id)init;

@end

@interface NSArray : NSObject

@end


当我们使用如下方式初始化NSArray时:

NSArray *array = [[NSArray alloc] init];

按照Cocoa的命名规则,语句[NSArrayalloc]的类型就是NSArray*因为alloc的返回类型属于关联返回类型。同样,[[NSArrayalloc]init] 的返回结果也是NSArray*。

三、instancetype作用

1、作用

如果一个不是关联返回类型的方法,如下:

@interface NSArray

+ (id)constructAnArray;

@end

当我们使用如下方式初始化NSArray时:

[NSArray constructAnArray];

根据Cocoa的方法命名规范,得到的返回类型就和方法声明的返回类型一样,是id。

但是如果使用instancetype作为返回类型,如下:

@interface NSArray

+ (instancetype)constructAnArray;

@end

当使用相同方式初始化NSArray时:

[NSArray constructAnArray];

得到的返回类型和方法所在类的类型相同,是NSArray*!

总结一下,instancetype的作用,就是使那些非关联返回类型的方法返回所在类的类型!

2、好处

能够确定对象的类型,能够帮助编译器更好的为我们定位代码书写问题,比如:

[[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; // "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"

[[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)

上例中第一行代码,由于[[NSArray alloc]init]的结果是NSArray*,这样编译器就能够根据返回的数据类型检测出NSArray是否实现mediaPlaybackAllowsAirPlay方法。有利于开发者在编译阶段发现错误。

第二行代码,由于array不属于关联返回类型方法,[NSArray array]返回的是id类型,编译器不知道id类型的对象是否实现了mediaPlaybackAllowsAirPlay方法,也就不能够替开发者及时发现错误。


返回值是instancetype类型时, Xcode编译器会随时检查 instancetype对应的真实类型,  如果发现接收对象的指针和真实类型不匹配是会给程序猿⚠️ ,  而id类型的只有在运行时才会检测到,不方便程序猿随时验证代码. 所以各有优劣, 应根据具体情况选择.

不同点:

    1.id在编译的适合不能判断对象的真实类型,instancetype在编译的时候可以判断对象的真实类型

    2.id可以用来定义变量,可以作为返回值类型,可以作为形参类型;instancetype只能作为返回值类型

 注意:以后凡是自定义构造方法,返回值类型尽量使用instancetype,不要使用id


id类型

在Objective-C 中,id 类型是一个独特的数据类型。在概念上,类似Java 的Object 类,可以转换为任何数据类型。换句话说,id 类型的变量可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上是一个指向这种对象的实例变量的指针。例如,下面定义了一个id类型的变量和返回一个id类型的方法:

id anObject;  

- (id) newObject: (int) type; 

id 和void *并非完全一样。下面是id在objc.h中的定义:

typedef struct objc_object {  

Class isa;  

} *id; 

从上面看出,id 是指向struct objc_object 的一个指针。也就是说,id 是一个指向任何一个继承了Object(或者NSObject)类的对象。需要注意的是id 是一个指针,所以在使用id的时候不需要加星号,比如,

id foo=nil; 

上述语句定义了一个nil 指针,这个指针指向NSObject 的任意一个子类。而“id*foo=nil;”则定义了一个指针,这个指针指向另一个指针,被指向的这个指针指向NSObject的一个子类。

在Objective-C中,id取代了int类型成为默认的数据类型(在C语言中,int是默认的函数返回值类型),关键字nil 被定义为空对象,也就是值为0 的对象。

你可能感兴趣的:(instancetype和id)