今天 allen 问了我一个问题,id和NSObject之间有什么区别,经过大神henry指点给我这个网址 id vs NSObject* vs id<NSObject>,大致明白其中的原理。
id foo1;
NSObject *foo2;
id<NSObject> *foo3;
-
id
在实际编码中,我们经常看到第一个,在编译器眼中,id仅仅意味着一个指向对象的指针,关于这个对象的信息,编译器需要等到runtime才能确定。因此,在程序中,不管对由id指向的对象发送任何消息,编译器都不会有任何报错,就像我们常见的id obj = [[Foo alloc] init]一样,由于Foo alloc返回的是id对象,因此对其调用init方法与对其调用initWithbalbalbal等方法都是可以的(当然,现在的编译器会只能地警告,之前没见过这个selector)。 -
NSObject
而id指向的对象并不全是NSObject的子类,当我们指定一个类为NSObject时,编译器就确切地知道了该类的所有信息,因此,当我们对该对象发送NSObject没有声明的方法时,编译器就会果断报错 = =
在别的语言中,声明一个类似NSObject的对象并进行操作是非常普遍的,因为NSObject意味着所有类的基类,但在objc这门动态语言中,过于严格的类型检查是不受欢迎的,在框架中,并不是所有类都继承自NSObject,比如说NSProxy,尽管它声明了大多数与NSObject同样的方法,但它的基类并不是NSObject,这时候,id<NSObject>就发挥出作用了。 -
id<NSObject>
将一个对象声明为id<NSObject>,意味着编译器不对其作任何类型检查,但是这个对象所属的类默认实现名为NSObject的protrol(是的,也有一个协议叫NSObject)。其实,在实际操作中,我们往往不会去关心一个对象的所属的类,而是这个对象会响应什么方法,id<NSObject>表明了foo3这个指针指向了一个实现了NSObject协议的方法的类的对象。
因此我们应该在这三种方法中做出怎么样的选择呢,如果你是需要一个不需要任何类型检查的对象指针时,就使用 id 吧,它经常用于接收一些不确定返回值类型的函数返回值,也经常用于 delegate 上,因为在runtime时,delegate 所属的类并不重要,而是会通过 responseToSelector: 做对其相应的方法做检查。(当然也可能是通过协议指定)。
而当你需要一个严格类型检查的对象指针时,相信我,使用 id<NSObject> 吧~因为在现有框架中,我们会大量使用 NSProxy ,这个不属于 NSObject 子类的东东,并且,我们只需要确认一个对象能用响应一系列 NSObject 的方法,我们根本不关系它所属的类。










网友评论