iOS之id和NSObject *的区别
2020-10-16 本文已影响0人
无极战思
1.id
在objc.h
中定义
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
从上面可以看出,id
的本质
是struct objc_object结构体指针
,可以指向任何OC对象。
注意:
这里说的是指向OC对象
,像int、NSInteger
这些基本数据类型
是不
可以的,将id
指向int
会报错
OC中的基类除了NSObject之外,还有一个NSProxy虚类
。因此,id
相比NSObject *
指向的对象范围要更广
。
2.id
是动态
数据类型,而NSObject *
是静态
数据类型,默认情况下
所有的数据类型都是静态
。
-
id
类型的实例在编译
阶段不会
做类型检查,会在运行时
确定,而类NSObject
的实例在编译期要做编译检查
,保证指针指向是其NSObject类或其子类,当然,实例的具体类型
也要在运行时
才能确定,这也就是iOS三大特性之一的多肽
。 -
静态类型
在编译
时就知道变量的类型
,编译时就知道变量的类型,在编译
的时候就可以访问对象的属性
和方法
,如果访问了不属于
静态类型的属性
和方法
,那么编译器就会报错
,而动态数据类型
在编译
的时候并不知道
变量的真实
类型,只有在运行时的时候才知道它的真实类型,因此编译时候如果访问了不属于
动态类型的属性
和方法
,编译器不会
报错,导致运行
时的错误,这也是动态数据类型
的弊端
。
举例如下:#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface People : NSObject -(void)eatFood; @end NS_ASSUME_NONNULL_END #import "People.h" @implementation People -(void)eatFood { NSLog(@"eatFood"); } @end #import "ViewController.h" #import "People.h" @interface ViewController () @end @implementation ViewController -(void)drinkWater { NSLog(@"drinkWater"); } - (void)viewDidLoad { [super viewDidLoad]; id test = [People new]; [test drinkWater]; // Do any additional setup after loading the view. } @end
从上面代码我们不难看出,drinkWater
方法并不是
id指针指向对象的方法
,调用了不是自己
的方法,但是编译
并没有
报错,只有运行时
才报错了。