Objective-C中的instancetype和id…

作者:韩俊强

原文地址:http://control.blog.sina.com.cn/admin/article/article_add.php

转载请注明出处

一、什么是instancetype

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

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

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

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

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

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

  1. @interface NSObject  
  2. + (id)alloc;  
  3. - (id)init;  
  4. @end  
  5.   
  6. @interface NSArray : NSObject  
  7. @end

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

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

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

[objc] view plaincopy

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

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

 

三、instancetype作用

1、作用

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

[objc] view plaincopy

  1. @interface NSArray  
  2. + (id)constructAnArray;  
  3. @end  

 

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

[objc] view plaincopy

  1. [NSArray constructAnArray];  

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

 

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

[objc] view plaincopy

  1. @interface NSArray  
  2. + (instancetype)constructAnArray;  
  3. @end  

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

[objc] view plaincopy

  1. [NSArray constructAnArray];  

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

 

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

2、好处

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

[objc] view plaincopy

  1. [[[NSArray alloc] init] mediaPlaybackAllowsAirPlay]; //  "No visible @interface for `NSArray` declares the selector `mediaPlaybackAllowsAirPlay`"  
  2.   
  3. [[NSArray array] mediaPlaybackAllowsAirPlay]; // (No error)  

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

 

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

四、instancetype和id的异同

1、相同点

都可以作为方法的返回类型

2、不同点

①instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;

②instancetype只能作为返回值,不能像id那样作为参数,比如下面的写法:

[objc] view plaincopy

  1. //err,expected a type  
  2. - (void)setValue:(instancetype)value  
  3. {  
  4.     //do something  
  5. }  

就是错的,应该写成:

[objc] view plaincopy

  1. - (void)setValue:(id)value  
  2. {  
  3.     //do something  
  4. }  

 

五、参考

1、http://nshipster.com/instancetype/

2、http://clang.llvm.org/docs/LanguageExtensions.html#objective-c-features

时间: 2024-12-10 03:26:59

Objective-C中的instancetype和id…的相关文章

JSP中如何取得MSSQL数据库表中自动增长的ID主键值?

JSP中如何取得MSSQL数据库表中自动增长的ID主键值? 如:建一个表student有属性列userid,username其中userid为INT类型只读自动加1的主键(也就是每插入一条记录都会自动加1),那么如何在JSP中得到当前插入行的userid值(比如:我向表里插入了三条记录,在我插入第三条记录时userid的值应为3,那么如何得到这个3)? 先创建存储过程: CREATE PROCEDURE addrec   (   @OutID int output,   @Name varcha

jstack:将Process Explorer中看到的进程ID做16进制转换,到ThreadDump中加上0x 前缀即能找到对应线程(转)

原文链接:http://www.iteye.com/topic/1133941 症状: 使用Eclipse win 64位版本,indigo及kepler都重现了,使用tomcat 6.0.39,jdk1.6.u45及1.7u45均尝试了,也重现. 重现步骤很简单,使用debug模式启动时较容易出来,debug启动tomcat,(我的是webapp)然后在页面上随便点点即发现eclipse僵死,且任何从浏览器发出的请求都卡住不能被接收执行. 1.然后从任务管理器直接杀掉eclipse对应的jav

oracle-Oracle中varchar2类型的id为自动增长

问题描述 Oracle中varchar2类型的id为自动增长 Oracle中id的类型为varchar2(10)主键,怎样创建自动增长的id 解决方案 可以的,使用序列 创建序列 create sequence SEQ_CEID minvalue 1 maxvalue 9999999999 start with 41 increment by 1 cache 20; 创建表,插入,查询 create table table_f ( id varchar(10) primary key, name

关于servlet中doget的”/xxxServlet/id“的使用方式,doget里是out.print(),我怎么用上述方式在jsp里的某个位置输出

问题描述 关于servlet中doget的"/xxxServlet/id"的使用方式,doget里是out.print(),我怎么用上述方式在jsp里的某个位置输出.就像<imgsrc="/Instagrim/ThumbServlet/<%=p.getSUUID()%>">.图片可以有一个src来调用那个doget.但是文本怎么办.我的doget里用的是out.print("jasdksjdfhk")我就想用"/

对象-SSH中怎么实现根据id删除一条数据?求大神!!

问题描述 SSH中怎么实现根据id删除一条数据?求大神!! 如题,小白一枚,主要是this.getHibernateTemplate().delete();方法只能传对象,个人感觉太复杂,自己如果写一个删除不用它里面的方法应该怎么写? 解决方案 public void delete(int id){ String hql="delete Person as p where p.id=?"; Query query=session.createQuery(hql); query.setI

数据-C# sql 查找每个分库中某表某ID字段重复的记录

问题描述 C# sql 查找每个分库中某表某ID字段重复的记录 目前30个分库中,每个库目前至少有100万条记录,每个库同有一个数据表A,表结构相同.每个表的主键叫recordID,但是各个分库间会重复不唯一.需求一个思路.忽略数据表设计问题,目前就是做出这个工具而已,表设计问题不管. 目前我是利用Sorteddiction的contains方法判断重复,但是会出现内存溢出的问题.OutOfMemory 解决方案 建临时表,先把所有表的recordID集中起来,然后再判断重复.

rototium id-robotium中如何通过区分ID相同的两个view

问题描述 robotium中如何通过区分ID相同的两个view 本人正在自学robotium,java基础很差,希望回答的大仙们尽量具体一些,最好每一行都有说明.现在说明一下我遇到的问题:界面上有两个camera,两个camera的id是一样的,我现在想点击进入第一个camera,请问如何实现.因为我现在只学习apk的robotium,请不要提供针对源码的解决方法.

entity-HIbernate中我没有指定id最后却有id生成

问题描述 HIbernate中我没有指定id最后却有id生成 @Entity @DiscriminatorValue("员工") public class Employ extends Person4 { private String title; private double salary; @ManyToOne(cascade=CascadeType.ALL,targetEntity=Manger.class) @JoinColumn(name="manger_id&qu

Android的include中,怎么获取不同include中的相同布局中的控件id

问题描述 Android的include中,怎么获取不同include中的相同布局中的控件id 比如,我的layout.xml中只有一个ImageButton 在另一个tablelayout.xml中通过include调用layout.xml 但是我想在activity中获取不同include中的imageButton的ID 解决方案 系统不会管你在layout中声明了多少个相同ID的View的,通过findViewByID查找控件时,它只关注子View内是否有符合ID的View,其他同ID的V