oc- isa superclass 类 原类
OC对象 主要分三种:
instance 对象(实例对象)
class 对象(类对象)
meta-class 对象 (元类对象)
1:一个实例对象 在内存中存储的信息:isa指针、其他变量(这个是成员变量的值,比如说,self.age = 10, 10放在里面)
2:类对象
NSObject *objec1 = [[NSObject alloc] init];
NSObject *objec2 = [[NSObject alloc] init];
// 获取类对象的三种方式
Class objectClass1 = [objec1 class];
Class objectCalss2 = [objec2 class];
Class objectClass3 = object_getClass(objec1);
Class objectClass4 = object_getClass(objec2);
Class objectClass5 = [NSObject class];
一个类的类对象是唯一的,在内存中是一份的,所以上述objectClass1、2、3、4、5地址是一样的
2018-07-04 20:39:35.659080+0800 new[4539:831047] 0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140,0x7fffb08b9140
类对象在内存中存储的信息:isa指针、superclass指针、类的属性信息(@property)、类的对象方法信息(instance method)(减号的方法)、类的协议信息(protocol)、类的成员变量信息(ivar)(这个成员变量是 成员变量的名字、还有成员变量的类型,比方说 string类型,名字叫age)3:meta-class 元类对象
获取元类对象
跟class和实例对象不是一种地址
class方法返回的就是类对象,不管你调用多少次,[[NSObject class] class]
元类对象在内存中储存的信息:类方法。
objectMetaClass是NSObject的meta-Class对象
每个类在内存中有且只有一个metal-Class对象
meta-Class对象和class对象的内存结构是一样的,但是用途不一样,在内存中存储的信息主要包括:isa指针、superclass、类方法信息。
可以判断是否是元类对象。:
class_isMetaClass(objectMetaClass);
object_getClass与objc_getClass分别是什么意思
A>: Class objc_getClass(const char *name)
a:传入的是字符串类名,返回对应的类对象。
B>: Class object_getClass(id obj)
a:传进去的obj可能是instance对象、class对象、meta-class对象
b:如果是instance对象,返回class对象
c:如果是class对象,返回的是meta-class对象
d:如果是meta-class对象,返回的是NSObject(基类)的meta-class对象。
C>: -(Class)class 、+(Class)class
返回的就是类对象
isa指针:
class对象的superclass指针:Student继承自Person,Person继承自NSObject。当Student实例变量去调用实例方法时的过程。
@interface Person : NSObject
{
int _df;
}
- (void)personMethod;
@end
@implementation Person
- (void)personMethod
{
}
@end
@interface Student : Person
{
double _no;
}
- (void)studentMethod;
@end
@implementation Student
- (void)studentMethod
{
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
Student *stu = [[Student alloc] init];
[stu personMethod];
}
return NSApplicationMain(argc, argv);
}
这个原理过程就是下面图中所示,stu先按照上图所示的,stu的实例对象的isa指针,找到本身stu类(因为类里有对象方法,同时有superclass指针,)发现并未有该方法,根据superclass指针,找到Person的类对象,就能够找到Person类的对象方法,正好有刚调用的personMehod方法,即可实现。假设Student类对象调用 load方法,那么过程就是下面图中所示:Student类根据isa指针找到自己的meta-class对象,在元类对象中并未发现load方法,就会根据superclass找到父类的meta-class对象,也就是Person的元类对象,发现也没有,再根据person原类对象的superclass找到父类也就是NSObject的meta-class对象,从而找到load方法。这里需要注意,假设NSObject没有load方法,那么现在NSObject这个基类的meta-class的superclass会找到NSObject的class,如果再没找到,才会报错。
总结一下:就是superclass找的是类方法 都是找的meta-class对象 如果找的是实例方法 ,那么找的都是类对象。
每一个类 都有自己的元类对象
假设Person和Student都有实例test方法。【student test】调用的时候,会直接调用student的test方法。原因:面向对象的思想的话是子类重写父类,那么肯定会调用子类的方法。如果按照上面的本质去解释的话:子类isa指针找到本类class对象,发现有test方法,那么它就直接执行了,不会再找父类了。
如果是
验证问题:
这个是NSObject分类,只实现了实例方法test。
#import "NSObject+test.h"
@implementation NSObject (test)
- (void)test
{
NSLog(@"sfd");
}
@end
这里是person方法,并未实现test类方法
@interface Person : NSObject
+ (void)test;
@end
@implementation Person
@end
#import "NSObject+test.h"
int main(int argc, const char * argv[]) { @autoreleasepool {
[Person test];
}
return NSApplicationMain(argc, argv);
}
那么这个能够调用? 是否会报错? 答案很明显,不会
2018-07-10 20:08:51.314998+0800 new[1765:218776] sfd
原因就是上面基类的meta-class方法如果没有找到对应的类方法的时候,它的superclass指针会指向基类的class对象,也就是NSObject类,找到了test方法,所以就调用了。对于本质objc_Send()方法而言,是没有减号和加号的区别方法的,所以直接调用。注意:
isa不是直接指向本类的对象的,从64bit开始,需要一次运算才能计算出真实的地址
但是superclass是直接指向的,并不需要转换
2:对象的isa指针指向哪里?
instance对象isa指向class对象
class对象isa指向meta-class对象
meta-class对象isa指向基类meta-class对象
3:OC的类信息存放在哪里?
对象方法、属性、成员变量、协议信息存放在class对象中
类方法存在meta-class对象中
成员变量的具体值,存放在instance对象
推荐阅读
-
c# 类实例序列化反序列化json文件 (原发布 csdn 2017-10-01 20:02:12)
-
EasyASP v1.5发布(包含数据库操作类,原clsDbCtrl.asp)第1/2页
-
oc- isa superclass 类 原类
-
【原】Spring测试类代码
-
EasyASP v1.5发布(包含数据库操作类,原clsDbCtrl.asp)第1/2页
-
c# 类实例序列化反序列化json文件 (原发布 csdn 2017-10-01 20:02:12)
-
phpcms新增子类后,原分门别类内容找不到的解放方法
-
php中分页原与与分页类_PHP教程
-
php中分页原与与分页类
-
字节码编程,Javassist篇三《使用Javassist在运行时重新加载类「替换原方法输出不一样的结果」》