iOS开发48-iOS id和instancetype的使用区别

iOS开发48-iOS id和instancetype的使用区别

Objective-C 是一门正迅速发展的语言,这种发展速度在别的现有语言中是不曾有过的。ARC,object literals,subscripting,blocks:在短短的三年时间里,Objective-C编程的许多方式发生了改变(变得更好)。

 1、关于id      

 id是动态类型,程序只有在运行时才能确定它的具体类型。是指向哪个对象的。id是一种通用的对象类型,它可以用来存储属于任何类的对象也可以理解为万能指针 


注意 在id的定义中,已经包好了*号。id指针只能指向os的对象。 

id 类型的定义
Typedef struct objc object{
   Class isa;
} *id;

局限性:调用一个不存在的方法,编译器会马上报错。

2、关于instancetype 

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

     只要一个类返回自身的实例,用instancetype就有好处。

iOS5之后推出了instancetype类型 

instancetype和id的异同 

        相同点:都可以作为方法的返回类型 


不同点 :
1,instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象; 
        2,instancetype只能作为返回值,不能像id那样作为参数, 


     instancetype只能作为返回值,id可以作为参数.

     -(void)setValue:(instancetype)value{}
      报错!应该写成下面的形式:
     -(void)setValue:(id)value{}


只要一个类返回自身的实例,用instancetype就有好处。
@interface Foo:NSObject
 - (id)initWithBar:(NSInteger)bar; // initializer
 + (id)fooWithBar:(NSInteger)bar;  // convenience constructor
@end


对于简易构造函数(convenience constructor-便利构造器),应该总是用instancetype。编译器不会自动将id转化为instancetype。id是通用对象,但如果你用instancetype,编译器就知道方法返回什么类型的对象。
这个问题不只有学术意义,比如,
[[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData]
在Mac OS X(只在该OS版本)中会报错
“Multiple methods named 'writeData:' found with mismatched result, parameter type or attributes.”
原因是NSFileHandle和NSURLHandle都提供writeData:方法。
由于[NSFileHandle fileHandleWithStandardOutput] 返回的类型是id,编译器并不确定请求了哪个类的writeData:方法。
你可以用[(NSFileHandle *)[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData];

NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardOutput];
[fileHandle writeData:formattedData];
来绕过。
当然,更好的方法是声明fileHandleWithStandardOutput的返回类型为instancetype。

(注意:这段样例代码在iOS中并不会报错,因为iOS中只有NSFileHandle提供writeData:方法。

但length等方法则会,UILayoutSupport会返回CGFloat,而NSString则会返回NSUInteger)




initializer的情况更复杂,当你输入
- (id)initWithBar:(NSInteger)bar
编译器会假设你输入了
- (instancetype)initWithBar:(NSInteger)bar


对于ARC而言,这是必须的。Clang Language Extensions的相关结果类型(Related result types 关联类型)也讲到了这一点。也许别人会据此告诉你不必使用instancetype,但我建议你用它。下面解释我为什么如此建议。
使用instancetype有三点好处:
1、明确性。代码只做你让它做的事,而不是其他。
2、程式化。你会养成好习惯,这些习惯在某些时候会很有用,而且肯定有用武之地。
3、一致性。让代码可读性更好。
明确性用instancetype代替id作为返回值的确没有技术上的好处。但这是因为编译器自动将id转化成了instancetype。你以为init返回的值类型是id,其实编译器返回了instancetype。
这两行代码对于编译器来说是一样的:
- (id)initWithBar:(NSInteger)bar;
- (instancetype)initWithBar:(NSInteger)bar;
但在你眼里,这两行代码却不同。
你不该学着忽视它。
模式化在使用init等方法时的确没有区别,但在定义简易构造函数(便利构造器)时就有区别了。
这两行代码并不等价:
+ (id)fooWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
如果用instancetype作为函数的返回类型,就不会出错。
一致性:
最后,想象把所有东西放到一起时的情景:
你想要一个init方法和一个简易构造函数。如果你用id来作为init函数的返回类型,最终代码如下:
- (id)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
但如果你用instancetype,代码如下:
- (instancetype)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
代码更加一致,可读性更强。
它们返回相同的东西,这一点一目了然。结论除非你有意为旧编译器写代码,不然你在合适的时候都应该用instancetype。
在写一条返回id的消息前,问自己:这个类返回实例吗?如果返回,用instancetype。肯定有需要返回id的时候,但你用instancetype的频率应该会更高。






著作权声明:本文由http://my.csdn.net/Nathan1987_原创,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢

你可能感兴趣的:(iOS开发)