对于OC对象,引用以及isa的理解
程序员文章站
2024-03-23 21:23:46
...
1、使用类创建一个对象
Person p =
[[Person alloc]init];
1)Person * p 表示创建一个Person类型的引用,引用名为p。
事实上在objc的runtime中,对象是用
objc_object 结构体表示的。所以这时指明引用的类型只是为了编译和编辑方便。
如不指明p的类型,p就无法调用Person中的方法和属性。(强行调用要报错的,除非强转否则无法通过编译)
2)[Person alloc]表示创建一个Person类型的对象并为其分配内存空间。
在堆内存中申请合适的空间,在空间中,根据类的模板,创建对象。
对象中只有属性,没有方法 。isa指针,指向代码段中的类。
如何访问对象的属性:指针名字->属性名(根据指针,找到指针指向的对象,再找到对象中的属性来访问)
如何调用方法:现根据指针的找到对象,对象发现要调用方法,在*对象的isa指针找到类,然后调用类里面的方法
(元类里保存了这个类的类方法列表)
3)init 执行初始化方法。
2、扩展 如何理解父类引用指向子类对象这一行为。
引用的本质就是一个常量指针,而限制其指向的是声明的引用类型。引用是什么类型在runtime时并不重要(此处的不重要仅指在调用方法和属性的过程中),因为所有的对象都是以objc_object 结构体表示的。所以理论上一个引用可以指向任何类型的对象,但这样做存在极大的不确定因素。
如:
A{funA,funB}//类A包含两个方法 funA和funB
B{funB,funC}//类B包含两个方法 funB和funC
//类A中的funB与类A中的funB仅仅是方法名一致
A a = [B new];
执行 [a funA] 报错!消息实际上发送给B的实例对象,但找不到funA。
执行 [a funB] 正常!消息实际上发送给B的实例对象,能找到funB。该funB是类B中的方法
执行 [a funC] 无法通过编译。
但是父类引用指向子类对象却是例外,因为子类继承了父类中的所有方法属性。因而在执行是一定不会发生错误。